1160: 方格填数
时间限制: 1 Sec 内存限制: 128 MB提交: 74 解决: 35
[ 提交][ 状态][ 讨论版]
题目描述
如上面的10个格子,填入0~9的数字,不能重复(原先已经填了一部分数字),要求:连续的两个数字不能相邻(左右,上下,对角都算相邻)。例如:数字0和1不能放在一起。
问:一共有多少种可能的填数方案?
输入
输入多组测试数据。
每组测试数据有三行,第一行三个整数,第二行四个整数,第三行三个整数,之间用空格隔开,分别代表每个空格所填的数,如果原先没有数,则填-1。
输入数据保证不重复数字,不保证连续数字不相邻。
输出
每组测试数据输出一行。
输出表示方案数目的整数。
样例输入
-1 -1 -1
-1 -1 -1 -1
-1 -1 -1
0 1 -1
-1 -1 -1 -1
-1 -1 -1
1 3 5
-1 -1 -1 -1
-1 -1 -1
样例输出
1580
0
8
思路:首先明确这是一道搜索的题目,那么就需要标记,由于每个数字只能用一次,定义b[10]作为标记数字0-9是否已经填入了,首先可以将这个矩阵补全,看做为一个3*4的矩阵,将第一个和最后一个用作别的数字进行代替,然后用for()输入数组,接下来就是对数组进行遍历,b[a[][]]=1对用过的数字进行标记,然后判定条件填数
代码如下:
//方格填数
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
int a[4][5],b[10],count;
int fun1(int i,int j,int k)
{
if(j>0&&abs(k-a[i][j-1])==1)//判断所填数字左面是否满足条件;
{
return 0;
}
if(i>0&&abs(k-a[i-1][j])==1)//判断数字上面是否满足条件
{
return 0;
}
if(i>0&&j>0&&abs(k-a[i-1][j-1])==1)//判断左上
{
return 0;
}
if(i>0&&j<3&&abs(k-a[i-1][j+1])==1)//判断右上;
{
return 0;
}
return 1;
}
void fun(int x)
{
int i,j;
int n=x/4;
int m=x%4;
if(x==11)
{
count++;
return;
}
if(a[n][m]==-1)
{
for(i=0;i<=9;i++)/
{
if(!b[i]&&fun1(n,m,i))//判断i这个数字是否用过,同时满足相邻、斜线数字绝对值不为一;
{
a[n][m]=i;//填数字
b[i]=1;//标记i已经用过
fun(x+1);
a[n][m]=-1;//回溯
b[i]=0;
}
}
}
else if(fun1(n,m,a[n][m]))//判断已经填入的数字书否满足条件
{
fun(x+1);
}
}
int main()
{
while(scanf("%d",&a[0][1])!=EOF)
{
int i,j;
count=0;
memset(b,0,sizeof(b));//对b数组进行初始化
for(i=0,j=2;j<4;j++)
{
scanf("%d",&a[i][j]);
}
for(i=1,j=0;j<4;j++)
{
scanf("%d",&a[i][j]);
}
for(i=2,j=0;j<3;j++)
{
scanf("%d",&a[i][j]);
}
a[0][0]=-3;//将第一个和最后一个用其他小鱼-1的数字代替;
a[2][3]=-3;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
if(a[i][j]>=0)
{
b[a[i][j]]=1;//遍历a[][],并标记已经使用过的数字;
}
}
}
fun(1);
printf("%d\n",count);
}
return 0;
}