洛谷P1896互不侵犯King
阿新 • • 發佈:2018-11-11
這道題也是一道狀壓DP。
http://www.cnblogs.com/Ronald-MOK1426/p/8456798.html
這個部落格寫的比較詳細。
其實入門了第一道狀壓DP:https://blog.csdn.net/King8611/article/details/82771818後這道題還是挺容易的。
不過dp加了個關係。
dp[i][j][k]表示第i個狀態為j的情況下,當前擺放到這一層棋數為k的情況
然後其他和之前的大同小異:
import java.util.*; import java.io.*; public class Main { static int state[],stateLen; //表示所有可能狀態,長度 static int num[]; //表示每種狀態下可能擁有的個數 static long dp[][][]; //dp[i][j][k]表示第i個狀態為j的情況下,當前擺放到這一層棋數為k的情況` static int n,m; static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static void main(String[] args) throws Exception { init(); setState(); setDp(); System.out.println(getAns()); } static void init() throws Exception{ n=getInt(); m=getInt(); } static void setState() { state=new int[1000]; num=new int[1000]; int totle=1<<n; for(int i=0;i<totle;i++) if(isOk(i)) { state[stateLen++]=i; for(int j=i;j!=0;j=j>>1) num[stateLen-1]+=j&1; } } static void setDp() { dp=new long [15][1000][100]; for(int i=0;i<stateLen;i++) dp[0][i][num[i]]++; //迴圈計算dp,我也不知道為啥居然不超時 for(int i=1;i<n;i++) { for(int j=0;j<stateLen;j++) { for(int k=0;k<stateLen;k++) { if(isOk(j,k)) { for(int l=0;l<=m;l++) { if(num[j]+l<=m) dp[i][j][num[j]+l]+=dp[i-1][k][l]; } } } } } } static long getAns() { long ans=0; for(int i=0;i<stateLen;i++) ans+=dp[n-1][i][m]; return ans; } //判斷這層是否和上一層衝突 static boolean isOk(int i,int j) { int a=state[i],b=state[j]; return ((b&a)==0)&&(((b<<1)&a)==0)&&((b>>1&a)==0); } //判斷這一層是否和這一層衝突 static boolean isOk(int x) { return (x&(x<<1))==0; } static int getInt() throws Exception{ in.nextToken(); return (int) in.nval; } }