【蓝桥杯2016_C++】t3:方格填数
如下的10个格子
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
法一
全排列+check,可以把这个格子当成一个存放0~9的一维数组再进行全排列,把每种不符合要求的条件都列出来check一下:
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 5 int ans = 0; 6 bool check(){ 7 if(abs(a[0]-a[1])==1 || abs(a[0]-a[3])==1 || abs(a[0]-a[4])==1 || abs(a[0]-a[5])==1 8 || abs(a[1]-a[2])==1 || abs(a[1]-a[4])==1 || abs(a[1]-a[5])==1 || abs(a[1]-a[6])==1 9 || abs(a[2]-a[5])==1 || abs(a[2]-a[6])==1 10 || abs(a[3]-a[4])==1 || abs(a[3]-a[7])==1 || abs(a[3]-a[8])==1 11 || abs(a[4]-a[5])==1 || abs(a[4]-a[7])==1 || abs(a[4]-a[8])==1 || abs(a[4]-a[9])==1 12 || abs(a[5]-a[6])==1 || abs(a[5]-a[8])==1 || abs(a[5]-a[9])==1 13 || abs(a[6]-a[9])==1 14 || abs(a[7]-a[8])==1 15 || abs(a[8]-a[9])==1 16 ) return false; 17 else{ 18 ans++; 19 return true; 20 } 21 } 22 int main() 23 { 24 do{ 25 check(); 26 }while(next_permutation(a,a+10)); 27 cout<<ans; 28 return 0; 29 }
有一个手动实现全排列的模板:
1 /*考虑第k个位置,一般从0开始*/ 2 void f(int k) { 3 //出口 4 if (k == 10) { 5 bool b = check(); 6 if(b) 7 ans++; 8 return; 9 } 10 11 12 for (int i = k; i < 10; ++i) { 13 //尝试将位置i与位置k交换,以此确定k位的值 14 { 15 int t = a[i]; 16 a[i] = a[k]; 17 a[k] = t; 18 } 19 f(k + 1); 20 // 回溯 21 { 22 int t = a[i]; 23 a[i] = a[k]; 24 a[k] = t; 25 } 26 27 } 28 }
法二
check列出来可能很乱,还有一种方法,就是把方格扩展成5*6的二维数组,先把所有格子都初始化为-10(除了-1,其他负数比如-5、-7都可):
check改为把每个元素和它周围一圈的元素做差取绝对值判断,写起来就简洁很多。扩展方格是为了防止check时下标越界。
从第一个格子(1,2)开始,从0~9中选一个没有被标记过的填进去,然后把填进去的数标记成已访问;然后check提前剪枝,满足条件就下一层递归,否则格子恢复-10的值并continue。最后还要回溯,标记清零。
这种方法每填一个格子就会提前check剪枝,不像法一,全部排列完才进行判断,提高了效率。
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 int a[5][6]; 5 int vis[10]; 6 int ans = 0; 7 void init(){ 8 for(int i=0;i<5;i++) 9 for(int j=0;j<6;j++) 10 a[i][j] = -10; 11 } 12 bool check(int x,int y){ 13 for(int i = x-1;i<=x+1;i++) 14 for(int j = y-1;j<=y+1;j++) 15 if(abs(a[x][y]-a[i][j])==1) return false; 16 return true; 17 } 18 void f(int x,int y){ 19 if(x==3 && y==4){ //如果已经填完了最后一个格子 20 ans++; 21 return; 22 } 23 for(int i = 0;i<10;i++){ 24 if(vis[i]==0){ //从0~9选一个没有填过的数字 25 a[x][y] = i; 26 if(!check(x,y)){ //如果不满足check条件 27 a[x][y] = -10; //恢复并continue 28 continue; 29 } 30 vis[i] = 1; //满足条件,标记并继续填下一个格子 31 if(y==4) f(x+1,1); //换行 32 else f(x,y+1); //继续填右侧格子 33 //回溯 34 vis[i] = 0; 35 a[x][y] = -10; 36 } 37 } 38 } 39 int main() 40 { 41 init(); 42 f(1,2); 43 cout<<ans<<endl; 44 return 0; 45 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧