完全不會
先抄一遍代碼感受一下
1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 3860 Solved: 2261
[Submit][Status][Discuss]
Description
在N×N的棋盤裏面放K個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上
左下右上右下八個方向上附近的各一個格子,共8個格子。
Input
只有一行,包含兩個數N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案數。
Sample Input
3 2
Sample Output
16
據說很水啊
不過我連八皇后還是最近纔會的
#include<bits/stdc++.h>
using namespace std;
int n,m,all,cnt[512];
long long f[10][100][512];
bool c1[512],c2[512][512];
long long ans;
void pre()
{
int s;//猜測目的應該是要去掉一些顯然不成立的情況
//例如兩個國王在一起之類的
for(int i=0;i<=all;i++)
if((i&(i>>1))==0)
{
s=0;
for(int x=i;x;x>>=1) s+=(x&1);
//判斷國王的個數
cnt[i]=s;
c1[i]=1;//定義這個情況是合理的
}
for(int i=0;i<=all;i++)if(c1[i])
for(int j=0;j<=all;j++) if(c1[j])
if(((i&j)==0)&&((i&(j>>1))==0)&&((j&(i>>1))==0))
c2[i][j]=1;
//判斷兩種情況是否能和並
//首先兩種情況都需要合法,如果兩列不在同一個位置有點,且左右移也沒有
//那麼這兩種情況就可以放在一起
}
int main()
{
scanf("%d%d",&n,&m);
all=(1<<n)-1;//一串長度爲n的1
pre();
for(int i=0;i<=all;i++) if(c1[i]) f[1][cnt[i]][i]=1;//對於每種單個的情況 計數
for(int j=1;j<n;j++)//對於多個的情況計數
for(int k=0;k<=all;k++) if(c1[k])
for(int i=0;i<=all;i++)if(c1[i])
if(c2[k][i])
for(int p=cnt[k];p+cnt[i]<=m;p++)
f[j+1][p+cnt[i]][i]+=f[j][p][k];
//之後只要兩行各自合法且合併合法就轉移
long long ans=0;
for(int i=0;i<=all;i++) ans+=f[n][m][i];//將符合要求的情況加起來
printf("%lld",ans);
return 0;
}
仔細標上註釋發現其實蠻簡單的
代碼是抄的黃學長的。
所以可能需要強迫自己去跟着過程走一遍
注意要按程序運行順序