本文共 1300 字,大约阅读时间需要 4 分钟。
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
所得的方案数
3 2
16
N的个数是十分小的 (即使这样爆搜也会T飞!!)
设f[i][j][k]代表前i行放了k个,排列方式是j,(j的二进制形式就是排列方式)。
void dfs(int w,int sum,int num)//分别为排列情况,放的点的个数,到底几个点了{ if(num>=n) { sit[++cnt]=w; gs[cnt]=sum; return; } dfs(w,sum,num+1);//不防这个点 dfs(w+(1<
那么根据题意,这个方案与另一个方案是否冲突 就显而易见啦
第一行:到第几行了
第二行:这一行的的排列情况 第三行:这一行的的排列情况可以从上一行的哪几个状态转移过来。for(int i=2;i<=n;i++) for(int j=1;j<=cnt;j++) for(int k=1;k<=cnt;k++) { if(sit[j]&sit[k])continue; if((sit[j]<<1)&sit[k]) continue; if(sit[j]&(sit[k]<<1)) continue; for(int s=K;s>=gs[j];s--) f[i][j][s]+=f[i-1][k][s-gs[j]]; }
完整代码:
#includeusing namespace std;#define maxn 2005int cnt,n,K;int sit[maxn],gs[maxn];long long f[10][maxn][105];long long ans;void dfs(int w,int sum,int num){ if(num>=n) { sit[++cnt]=w; gs[cnt]=sum; return; } dfs(w,sum,num+1); dfs(w+(1< =gs[j];s--) f[i][j][s]+=f[i-1][k][s-gs[j]]; } ans=0; for(int i=1;i<=cnt;i++) ans+=f[n][i][K]; printf("%lld",ans); return 0;}
注意开long long。。。
转载地址:http://yyuci.baihongyu.com/