飞行棋
做题时间:2021.02.03
在一个的棋盘上,放置种不同颜色的棋子将棋盘填满,每一种有无限个,在任意一条从左上角到右下角的路径上不得出现任意两个相同颜色的棋子。问有多少种方案数。
样例一 2 2 4 0 0 0 0 样例二 3 3 5 0 0 0 0 0 0 4 0 0 样例三 3 3 5 0 0 0 0 0 1 0 0 0
样例一 48 样例二 24 样例三 24
搜索、剪枝
#include<cstdio> #include<iomanip> using namespace std; const int MOD=1e9+7; int cnt[20];//记录当前第i个颜色出现的次数 int f[20][20];//记录当前填色的情况 int a[20][20];//记录棋盘情况 int check(int x)//查找x中有多少个1,即之前已经填了多少个颜色 { int ans=0; while(x){ if(x&1) ans++; x>>=1; } return ans; } int n,m,k; int DFS(int x,int y) { if(y==m+1) x++,y=1; if(x==n+1) return 1; int now=f[x-1][y]|f[x][y-1];//剪枝2:获取当前所用的颜色总数 int p=-1,res=0; if(k-check(now)<n+m-x-y+1) return 0;//剪枝2:判断剩下的颜色是否大于之后的路径长度 for(int i=1;i<=k;i++){ if((now>>i-1)&1) continue;//剪枝1:如果在当前第i个颜色已经填过,则不合法 if(a[x][y]==i||a[x][y]==0){ cnt[i]++; f[x][y]=now+(1<<i-1);//将第i个颜色标记上 if(cnt[i]!=1){ res+=DFS(x,y+1); res%=MOD; } else{//剪枝3:所有第一次出现的颜色,方案数都是一样的 if(p==-1){ p=DFS(x,y+1); res+=p; res%=MOD; } else{ res+=p; res%=MOD; } } cnt[i]--; } } return res; } int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); if(a[i][j]) cnt[a[i][j]]++;//提前标记 } } printf("%d\n",DFS(1,1)%MOD); return 0; }
本文作者:lxzy
本文链接:https://www.cnblogs.com/Unlimited-Chan/p/14370903.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现