[蓝桥杯 2021 省 AB2] 国际象棋
题目
Description
众所周知, “八皇后” 问题是求解在国际象棋棋盘上摆放 8 个皇后,使得两两之间互不攻击的方案数。已经学习了很多算法的小蓝觉得 “八皇后” 问题太简单了,意犹末尽。作为一个国际象棋迷,他想研究在 N×M 的棋盘上,摆放 K 个马,使得两两之间互不攻击有多少种摆放方案。由于方案数可能很大,只需计算答案除以 1000000007 (即 1e9+7) 的余数。
如下图所示,国际象棋中的马摆放在棋盘的方格内,走 “日” 字, 位于 (x,y) 格的马(第 x 行第 y 列)可以攻击 (x+1,y+2),(x+1,y−2),(x−1,y+2),(x−1,y−2),(x+2,y+1),(x+2,y−1),(x−2,y+1),(x−2,y−1) 共 8 个 格子。
Input
输入一行包含三个正整数 N,M,K 分别表示棋盘的行数、列数和马的个数。
Output
输出一个整数,表示摆放的方案数除以 1000000007( 即 109+7)的余数。
Sample Input
4 4 3
Sample Output
276
思路
一道状压题;
与[SCOI2005] 互不侵犯差不多,只不过因为马可以攻击到下两行的地方,所以需要多开一维数组存上一行的状态;
用表示第行的状态,第行状态,并且到第行为止一共放了个马;
状态转移方程就为:
为当前行的马的数量,表示上上行的状态;
代码
#include<bits/stdc++.h> typedef long long ll; using namespace std; const ll mod=1e9+7; ll n,m,k; ll a[101][7],dp[101][21][1<<6][1<<6]; int main() { scanf("%lld%lld%lld",&m,&n,&k); dp[0][0][0][0]=1; for(ll i=1;i<=n;i++) for(ll x=0;x<=(1<<m)-1;x++) { ll sum=0; for(ll j=1;j<=m;j++) if(x&(1<<(j-1))) sum++;//统计当前行马的数量 for(ll y=0;y<=(1<<m)-1;y++) for(ll z=0;z<=(1<<m)-1;z++) { if(x&(z>>1)||x&(z<<1))//上上行与当前行互不攻击 continue; if(x&(y>>2)||x&(y<<2))//上一行与当前行互不攻击 continue; for(ll j=0;j<=k-sum;j++)//枚举到上一行为止马的总数 dp[i][j+sum][x][y]=(dp[i][j+sum][x][y]+dp[i-1][j][y][z])%mod; } } ll ans=0; for(ll x=0;x<=(1<<m)-1;x++) for(ll y=0;y<=(1<<m)-1;y++) ans=(ans+dp[n][k][x][y])%mod; printf("%lld",ans); return 0; }
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】