完全不会
先抄一遍代码感受一下
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;
}
仔细标上注释发现其实蛮简单的
代码是抄的黄学长的。
所以可能需要强迫自己去跟着过程走一遍
注意要按程序运行顺序