在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
标签:dfs 技术分享 alt sam lap des max end 运算
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
方案数。
#include<iostream> using namespace std; const int maxn=1<<11; int n,k,cnt[maxn]; bool c[maxn],c2[maxn][maxn]; int tot; long long ans,dp[10][100][maxn]; void df(){ for(int i=0;i<=tot;i++){ int s=0; if((i&(i>>1))==0){ for(int j=i;j;j=j>>1)s+=(j&1); c[i]=1;cnt[i]=s; } } for(int i=0;i<=tot;i++)if(c[i]) for(int j=0;j<=tot;j++)if(c[j]) if(((i&j)==0)&&(((j>>1)&i)==0)&&(((i>>1)&j)==0)) c2[i][j]=1; } int main(){ cin>>n>>k;tot=(1<<n)-1;df(); for(int i=0;i<=tot;i++)if(c[i])dp[1][cnt[i]][i]=1; for(int i=1;i<n;i++) for(int j=0;j<=tot;j++)if(c[j]) for(int l=0;l<=tot;l++)if(c[l]) if(c2[j][l]) for(int p=0;p<=k;p++) dp[i+1][cnt[l]+p][l]+=dp[i][p][j]; for(int i=0;i<=tot;i++)ans+=dp[n][k][i]; cout<<ans; return 0; }
by:s_a_b_e_r
以上是非常正经的s_a_b_e_r的题解
以下是非常不正经的wypx的题解
……
不过感觉他说的挺详细了就没我什么事了吧╮(╯▽╰)╭
做的时候没用什么c1[i]啊c2[i][j]啊什么的,感觉好麻烦x
在dp之前先dfs一遍
把所有可能的状态都压进一个vector里
然后dp的时候就不用枚举所有状态了,直接从vector里往外拿
f[i][j][x]表示处理到第i行,放了j个棋子,现在的状态编号是x
(其实他不用vector是因为他不会用x)
#include<iostream> #include<cstdio> #include<vector> using namespace std; const int N=200; int n,k,num[N]; bool d[10]; long long f[N][N][N]; vector<int>a; void dfs(int x) { if(x>n) { int ans=0; for(int i=1;i<=n;++i) { ans<<=1; if(d[i]){++ans;++num[a.size()];} } a.push_back(ans); return; } dfs(x+1); if(!d[x-1]) { d[x]=1; dfs(x+1); d[x]=0; } } int main() { scanf("%d%d",&n,&k); dfs(1); int tot=a.size(); for(int i=0;i<tot;++i) f[1][num[i]][i]=1; for(int i=1;i<n;++i) for(int x=0;x<tot;++x) for(int y=0;y<tot;++y) if( ((a[x]&a[y])==0) && (((a[x]<<1)&a[y])==0) && ((a[x]&(a[y]<<1))==0) ) for(int j=num[x];j+num[y]<=k;++j) f[i+1][j+num[y]][y]+=f[i][j][x]; long long ans=0; for(int i=0;i<tot;++i)ans+=f[n][k][i]; cout<<ans<<endl; return 0; }
by:wypx
s:今天的天空璋好花啊,音乐棒棒的x
w:快去做题>_<
标签:dfs 技术分享 alt sam lap des max end 运算
原文地址:http://www.cnblogs.com/ck666/p/7425023.html