骑士
来源:互联网 发布:青岛知行天下 编辑:程序博客网 时间:2024/06/10 07:17
骑士
Description
国际象棋中骑士的移动规则和中国象棋中的马是类似的,它先沿着一个方向移动两格,再沿着与刚才移动方向垂直的方向移动一格。
路径上的棋子并不会影响骑士的移动,但是如果一个骑士走到了一个放有棋子的格子,它就会攻击那个棋子。
现在有一个
那么使所有骑士互不攻击的摆放方式一共有多少种呢?
Input
一行:两个整数,
Output
一行:一个整数,为摆放的方案数。
Sample Input 1
3 2
Sample Output 1
28
Sample Input 2
4 4
Sample Output 2
412
Data Size & Time limit
对于所有的数据,
Solution
因为一个棋子所影响的范围只有两行,所以我们可以把每两行做成一个状态,然后dfs预处理出所有可行的状态,然后判断两两之间能否转移。
然后用dp即可求出答案。
需要注意的是,若
我竟然还用了组合数……
Code
#include <iostream>#include <cstdio>using namespace std;int n,k,cnt;int que[10000];int ss[10000];int jie[100000];int head[10000],nxt[1000000],data[1000000];bool already[1000000];double f[5][100][10000],ans;void dfs(int s1,int s2,int p,int sum){ if(p==n){ if(!already[(s1<<n)^s2]){ already[(s1<<n)^s2]=true; que[++que[0]]=(s1<<n)^s2; ss[que[0]]=sum; } return; } else{ dfs(s1<<1,s2<<1,p+1,sum); if(sum+1<=k){ if(!(s1&2))dfs(s1<<1,(s2<<1)|1,p+1,sum+1); if(!(s2&2))dfs((s1<<1)|1,s2<<1,p+1,sum+1); if(sum+2<=k)if(!(s2&2)&&!(s1&2))dfs((s1<<1)|1,(s2<<1)|1,p+1,sum+2); } }}void add(int x,int y){ nxt[cnt]=head[x];data[cnt]=y;head[x]=cnt++;}bool judge(int x,int y){ for(int i=0;i<n;i++){ if(i>=1){ if((que[y]&(1<<(2*n-i-1)))&&(que[x]&(1<<(2*n-i))))return false; if((que[y]&(1<<(n-i-1)))&&(que[x]&(1<<(n-i))))return false; } if(i<n-1){ if((que[y]&(1<<(2*n-i-1)))&&(que[x]&(1<<(2*n-i-2))))return false; if((que[y]&(1<<(n-i-1)))&&(que[x]&(1<<(n-i-2))))return false; } if(i>=2) if((que[y]&(1<<(2*n-i-1)))&&(que[x]&(1<<(n-i+1))))return false; if(i<n-2) if((que[y]&(1<<(2*n-i-1)))&&(que[x]&(1<<(n-i-3))))return false; } return true;}void work(){ jie[0]=1; int maxn=(n*n>k*k?n*n:k*k); for(int i=1;i<=maxn;i++)jie[i]=jie[i-1]*i;}double C(int tot,int xd){ return jie[tot]/jie[xd]/jie[tot-xd];}double done(int xd,int ll){ int tot=n; if(xd>n)return 0; for(int i=0;i<n;i++){ if(i>=1&&(que[ll]&(1<<(2*n-i))))tot--; else if(i<n-1&&(que[ll]&(1<<(2*n-i-2))))tot--; else if(i>=2&&(que[ll]&(1<<(n-i+1))))tot--; else if(i<=n-2&&(que[ll]&(1<<(n-i-3))))tot--; if(xd>tot)return 0; } return C(tot,xd);}double get_ans(int x){ double tmp=0; for(int j=0;j<=k;j++) tmp+=f[n>>1][k-j][x]*done(j,x); return tmp;}int main(){ freopen("knight.in","r",stdin);#ifndef DEBUG freopen("knight.out","w",stdout);#endif memset(head,-1,sizeof head); scanf("%d%d",&n,&k); dfs(0,0,0,0); if(n==1){ printf("%d\n",(k==1||k==0)?1:0); return 0; } else{ for(int i=1;i<=que[0];i++) for(int j=1;j<=que[0];j++) if(judge(i,j)) add(i,j); for(int l=1;l<=que[0];l++) f[1][ss[l]][l]=1; int limit=n>>1; for(int i=1;i<limit;i++) for(int j=0;j<=k;j++) for(int l=1;l<=que[0];l++)if(ss[l]<=j&&f[i][j][l]) for(int x=head[l];x!=-1;x=nxt[x]) if(j+ss[data[x]]<=k) f[i+1][j+ss[data[x]]][data[x]]+=f[i][j][l]; if((limit<<1)!=n)work(); if((limit<<1)==n)for(int l=0;l<=que[0];l++)ans+=f[limit][k][l]; else for(int l=0;l<=que[0];l++)ans+=get_ans(l); printf("%.0lf\n",ans); } return 0;}
0 0
- 骑士
- 骑士
- 骑士
- 骑士
- 骑士与骑士精神
- 青铜骑士
- 盔甲骑士
- 骑士问题
- 骑士精神
- 盔甲骑士
- 骑士巡游
- 克里夫兰骑士
- 骑士漫游
- 骑士征程
- [作业]骑士
- 骑士旅游
- 骑士周游
- 愁容骑士
- GLSL vary、atrribute、in、out的区别
- 学习Discuz! X3.2记录:快速回复插件,设置插件的快速回复内容
- 面试官在面试时让我去破解一个软件,我成功了
- ubuntu12.04安装tftp、配置tftp服务 错误解决方案
- python 数据类型String类型总结(二(2))
- 骑士
- MongoDB 索引
- python dict 遍历key效率问题
- 蓝牙聊天室App设计与实现
- 搭建http请求方式的git
- Android Bitmap 缓存策略
- AndroidStudio 混淆打包
- play_scala框架学习07 静态文件
- 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)