1. 程式人生 > >[BZOJ 1087] 互不侵犯KING

[BZOJ 1087] 互不侵犯KING

div TP HP col %d HR nbsp zoj ace

Link:

BZOJ 1087 傳送門

Solution:

思路基本上和 POJ 1185 炮兵陣地 完全相同

都是先對每一行的可能狀態進行預處理,只不過一個記錄最大值一個記錄方案數

不過再一次寫的時候還是犯了幾個**錯誤調了一會……

1、對$k$的枚舉要從0開始!

$dp$時很多時候為0的狀態都有初始值,一定要考慮邊界的取舍

2、位運算的括號問題

一開始$!st[j]\& st[l]$沒加括號……

位運算時還是多加一個括號保險吧……

Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long
ll; const int MAXN=1025; ll dp[15][MAXN][100],res=0; int n,m,st[MAXN],sum[MAXN],tot=0; int cal(int x) { int ret=0; for(;x;x>>=1) ret+=(x&1); return ret; } int main() { scanf("%d%d",&n,&m); int MAX=(1<<n)-1; for(int i=0;i<=MAX;i++) if(!(i&(i<<1
))) st[++tot]=i,sum[tot]=cal(i),dp[1][tot][sum[tot]]=1; for(int i=1;i<n;i++) for(int j=1;j<=tot;j++) for(int k=0;k<=m;k++) if(dp[i][j][k]) for(int l=1;l<=tot;l++) if(!(st[j]&(st[l]<<1)) && !(st[j]&(st[l]>>1)) && !(st[j]&st[l])) dp[i
+1][l][k+sum[l]]+=dp[i][j][k]; for(int i=1;i<=tot;i++) res+=dp[n][i][m]; printf("%lld",res); return 0; }

[BZOJ 1087] 互不侵犯KING