bzoj1087
又一道状压dp
查了半天错 又被位运算的优先级坑了
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<ctime> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define b(a) (1<<(a)) 9 #define clr(a,x) memset(a,x,sizeof(a)) 10 #define rep(i,l,r) for(int i=l;i<r;i++) 11 typedef long long ll; 12 using namespace std; 13 int read() 14 { 15 char c=getchar(); 16 int ans=0,f=1; 17 while(!isdigit(c)){ 18 if(c=='-') f=-1; 19 c=getchar(); 20 } 21 while(isdigit(c)){ 22 ans=ans*10+c-'0'; 23 c=getchar(); 24 } 25 return ans*f; 26 } 27 const int maxn=10,maxk=100; 28 int n,k; 29 ll d[maxn][maxk][b(maxn)]; 30 bool legal(int s) 31 { 32 while(s){ 33 if(s&1){ 34 if(s&b(1)) return 0; 35 } 36 s=s>>1; 37 } 38 return 1; 39 } 40 int cnt(int a) 41 { 42 int sum=0; 43 while(a){ 44 if(a&1) sum++; 45 a=a>>1; 46 } 47 return sum; 48 } 49 ll dp(int a,int b,int s) 50 { 51 if(d[a][b][s]!=-1) return d[a][b][s]; 52 if(b==0&&cnt(s==0)) return d[a][b][s]=1; 53 ll sum=0; 54 if(b-cnt(s)>=0){ 55 rep(i,0,b(n)){ 56 if(legal(i)&&legal(i|s)&&((i&s)==0)) 57 sum+=dp(a-1,b-cnt(s),i); 58 } 59 } 60 return d[a][b][s]=sum; 61 } 62 int main() 63 { 64 n=read(),k=read(); 65 clr(d,-1); 66 rep(i,0,b(n)) 67 rep(j,0,k+1) 68 d[1][j][i]=0; 69 rep(i,0,b(n)){ 70 if(legal(i)) d[1][cnt(i)][i]=1; 71 } 72 ll ans=0; 73 rep(i,0,b(n)) 74 if(legal(i)) 75 ans+=dp(n,k,i); 76 printf("%lld\n",ans); 77 return 0; 78 }
1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1977 Solved: 1174
[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