问题 F: 方格填数
时间限制: 1 Sec 内存限制: 128 MB
提交: 26 解决: 10
[提交] [状态] [讨论版] [命题人:admin]
题目描述
如下的10个格子
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
输入
没有任何输入
输出
输出一个整数
第一眼看到这个题的想法是用dfs,因为它是要连续搜索数据树上的一整个支路,即0-9这十个数字的不同组合,在此同时,题目中也提到了一个约束条件:“相邻或对角,数字不可连续”,所以在放每一个数字之前要设计一个检查方案检查它是否与之前所放的数字有冲突。
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define reset(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
using namespace std;
typedef long long ll;
typedef long double ld;
/*Although there will be many obstructs ahead of you,
the desire for victory still fills you with determination..*/
int dircetions[4][2]={0,-1,-1,0,-1,-1,-1,1};
//这四个方向向量都指向第二和第三象限,即之前放过的且与当前数相邻的数字。
int diagrams[99][99];
bool vis[23];
ll ans=0;
bool check(int r,int c,int current)//判定程序
{
int nx,ny;
for(int i=0; i<4; i++)
{
nx=r+dircetions[i][0];
ny=c+dircetions[i][1];
if(nx>=1&&nx<=3&&ny>=1&&ny<=4)
{
if(diagrams[nx][ny]==current-1||diagrams[nx][ny]==current+1)
//若数字有连续
return false;
}
}
return true;
}
void dfs(int r,int c)
{
if(r==3&&c==4)
{
ans++;
return ;
}//空格结束搜索
if(c>4)
dfs(r+1,1);
//超出当前列的容量,就要搜索下一行
else
{
for(int i=0; i<=9; i++)
{
if(vis[i]==0)//如果这个数字在当前递归到的步骤里没有使用
{
if(check(r,c,i))
{
vis[i]=true;//已使用
diagrams[r][c]=i;
dfs(r,c+1);
vis[i]=false;//回溯完毕,恢复原状
diagrams[r][c]=-1945;
}
}
}
}
}
int DETERMINATION()
{
for(int i=1; i<=9; i++)
for(int j=1; j<=9; j++)
diagrams[i][j]=-1945;
reset(vis,0);
dfs(1,2);
cout<<ans<<endl;
return 0;
}