scoi 互不侵犯 king
来源:互联网 发布:nyu数据科学录取名单 编辑:程序博客网 时间:2024/05/22 13:38
1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MBDescription
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
完成情况(大视野测评)
这应该是我做的第二道状压DP了,听说是入门题,但我高了很久,最终还是看受哥的博客才懂的。。。。。。。。
用 f [ i ] [ j ] [ S ] 表示前 i 行 , 用了 j 个国王, 当前行状态为 S 的方案数
那么 f [ i ] [ j ] [ S ] = ∑ f [ i - 1 ] [ m ] [ st ];
至于状态,由于只有2^9种,并不多,所以可以dfs预处理出所有的状态
其他的不多说了,记得用long long
具体看代码,注释没删,怕自己以后看不懂了。。。。。。。
C++ AC Code
#include<cstdio> #include<iostream> using namespace std; const int N=10; typedef long long LL; int n,k; LL f[N][N*N][1<<N];//f[i][j][S]表示前i行用了j个国王,第i行状态为S int a[1<<N],m=0,num[1<<N]; void pri(int s,int deep)//_Debug_正序打印01序列 { if(deep==n) {printf("%d",s);return;} pri(s>>1,deep+1); printf("%d",s&1); } void dfs(int x,int s) { if(x==n) { //pri(s,0);puts(""); a[++m]=s; for(int S=s;S;S=S>>1) num[s]+=(S&1); //printf("%d\n",num[s]); return; } dfs(x+1,s<<1); if((s&1)==0) dfs(x+1,(s<<1)+1); } bool can(int s,int st) { int S=s; S=(S|(s<<1))|(s>>1); bool flag=true; for(int i=1;i<=n;i++) { int ss=S&1,tt=st&1; S>>=1;st>>=1; if(ss&tt) {flag=false;break;} } if(flag) return true; else return false; } int main() { freopen("king.in","r",stdin); freopen("king.out","w",stdout); scanf("%d%d",&n,&k); dfs(0,0);//生成所有可能01方案 for(int idx=1,S=a[idx];idx<=m;idx++,S=a[idx]) f[1][num[S]][S]++; //for(int idx=1,S=a[idx];idx<=m;idx++,S=a[idx]) printf("%d ",f[1][1][S]); for(int i=2;i<=n;i++) for(int j=0;j<=k;j++) for(int idx=1,S=a[idx];idx<=m;idx++,S=a[idx]) for(int ix=1,st=a[ix];ix<=m;ix++,st=a[ix]) { //printf("%d %d ",i,j);pri(S,0);putchar(' ');pri(st,0);puts(""); if(can(S,st)&&j-num[S]-num[st]>=0) { f[i][j][S]+=f[i-1][j-num[S]][st]; //printf("%d\n",f[i][j][S]); } } //for(int idx=1,S=a[idx];idx<=m;idx++,S=a[idx]) printf("%d ",f[n][k][S]); LL res=0; for(int idx=1,S=a[idx];idx<=m;idx++,S=a[idx]) res+=f[n][k][S]; cout<<res<<endl; return 0; }
第二天再写,发现can()函数写麻烦了,换了一种写法
bool can(int s,int st) { int S=s; S=S|(s<<1)|(s>>1); S=S&((1<<n)-1); if((S&st)==0) return true; else return false; }
时间就快了60多ms
两次成绩:
0 0
- scoi 互不侵犯 king
- 【BZOJ 1087】【SCOI 2005】 互不侵犯King
- BZOJ 1087 SCOI 2005 互不侵犯King 状压DP
- BZOJ 1087 [SCOI 2005] 互不侵犯的king (状压DP)
- 【状压dp】【bzoj 1087】【SCOI 2005】互不侵犯King
- 【BZOJ 1087】【SCOI 2005】互不侵犯King 【状压DP】
- [BZOJ 1087][SCOI 2005] 互不侵犯King 状态压缩DP
- 互不侵犯king
- 互不侵犯king
- 互不侵犯King
- 互不侵犯 [Bzoj 1087,SCOI 2005]
- 【BZOJ1087 || SCOI2005】互不侵犯King
- SCOI05互不侵犯King题解
- [BZOJ1087][SCOI2005]互不侵犯King
- 【BZOJ】1087 互不侵犯King
- 【bzoj1087】[SCOI2005]互不侵犯King
- 【SCOI2005】【BZOJ1087】互不侵犯King
- [BZOJ1087] [SCOI2005]互不侵犯King
- orange's一个操作系统的实现--环境搭建
- WinCE C#程序,控制启动时只能启动一个程序,使用互斥量来实现,该实现方法测试通过
- runtime error R6025问题排查
- 上海爱立信笔试题-分享(真的就一道题)
- STL中vector容器begin(),end(),push_back()等相关函数
- scoi 互不侵犯 king
- poj 2309 树状数组
- 什么是Nginx
- 分支-02. 三角形判断(15)
- 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个排好序的数组的一个旋转。输出旋转数组的最小值。
- 分析linux共享内存的实现
- Mondriaan's Dream POJ2411 - 基础状压
- 雷神来袭 - 超强台风"威马逊"
- Codeforces Round #256 (Div. 2) B. Suffix Structures