方格填数
如下的10个格子
+--+--+--+
| | | |
+--+--+--+--+
| | | | |
+--+--+--+--+
| | | |
+--+--+--+
(如果显示有问题,也可以参看【图1.jpg】)
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
蓝桥杯的题,用暴力也是可以的,因为只需要一个结果。但是,用搜索却是很好的选择!
此题,由于方格是残缺的,这增加了一点困难,但是,我们补上残缺的角,便成为了规则的图形。
AC代码1.
此法,先用DFS枚举出所有的组合情况,在选择出满足条件的情况.
//OK
//1580
#include
#include
#include
#include
using namespace std;
const int maxn=0;
int a[3][4];
bool vis[10];
int dir[8][2]= {-1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1};
long long ans=0;
bool OK()
{
a[0][0]=a[2][3]=11;//
//补上残缺的两个角,
//其值绝对值大于10即可
for(int i=0; i<3; i++)
{
for(int j=0; j<4; j++)
{
for(int k=0; k<8; k++)
{
int xx=i+dir[k][0];
int yy=j+dir[k][1];
if(xx<0||xx>2||yy<0||yy>3)
continue;
if(abs(a[i][j]-a[xx][yy])==1)
return false;
}
}
}
return true;
}
void DFS(int p)
{
if(p==11)
{
if(OK())
{
ans++;
}
return;
}
int x=p/4;
int y=p%4;
for(int i=0; i<10; i++)
{
if(!vis[i])
{
vis[i]=true;
a[x][y]=i;
DFS(p+1);
vis[i]=false;
}
}
}
int main()
{
memset(vis,false,sizeof(vis));
DFS(1);
cout<
return 0;
}
AC代码2:
此法是上面代码的改进版,上边枚举出所有的情况再去判断是否满足,而此法在枚举每一位的时候就就判断是否合法(与左上,上,右上,左四个位置进行判断).
//OK
//1580
//http://www.voidcn.com/blog/riba2534/article/p-6520396.html
#include
#include
#include
#include
using namespace std;
const int maxn=0;
int a[3][4];
bool vis[10];
int ans=0;
int dir[4][2]={-1,-1,-1,0,-1,1,0,-1};
bool OK(int x,int y,int p)
{
a[0][0]=a[2][3]=11;
//上面一行代码是主函数注释代码的优化(替代)
for(int i=0;i<4;i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx<0||xx>2||yy<0||yy>3)
continue;
if(abs(p-a[xx][yy])==1)
return false;
}
return true;
}
void DFS(int p)
{
if(p==11)
{
ans++;
return;
}
int x=p/4;
int y=p%4;
for(int i=0;i<10;i++)
{
if(!vis[i]&&OK(x,y,i))
{
a[x][y]=i;
vis[i]=true;
DFS(p+1);
vis[i]=false;
}
}
}
int main()
{
memset(vis,false,sizeof(vis));
/**
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
a[i][j]=-100;
}
*/
DFS(1);
cout<
return 0;
}
AC代码3;
由于是0-9 10个数字的组合情况,我们就可以用10个数字生成的全排列,再去判断是否满足条件.注意一维数组与二维数组的转换.
#include
#include
#include
#include
using namespace std;
const int maxn=0;
bool vis[10];
int dir[8][2]={-1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1};
int a[12]={11,0,1,2,3,4,5,6,7,8,9,11};
bool OK()
{
for(int i=1;i<11;i++)
{
int x=i/4;
int y=i%4;
for(int j=0;j<8;j++)
{
int xx=x+dir[j][0];
int yy=y+dir[j][1];
if(xx<0||xx>2||yy<0||yy>3)
continue;
int p=xx*4+yy;
if(abs(a[i]-a[p])==1)
return false;
}
}
return true;
}
int main()
{
int ans=0;
do
{
if(OK())
{
ans++;
}
}while(next_permutation(a+1,a+11));
cout<
return 0;
}
参考博客:
http://www.voidcn.com/blog/riba2534/article/p-6520396.html