poj 2411 상태 압축 dp

7649 단어 poj
사고방식: 모든 줄을 2진법으로 간주하면 모든 합법적인 상태가 1로 인접한 개수는 반드시 짝수로 해야 한다.이렇게 하면 먼저 모든 합법적인 상태를 찾을 수 있다.한 층의 합법적인 상태가 모두 같지 않기 때문에, 하나의 수조로 저장할 수 있다.i-1행에서 i행으로 이동하는 상태는 dp[i][now|num[j]+=dp[i-1][k]이고 그 중에서 now는 (1<#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define Maxn 13 #define inf 0x7fffffff using namespace std; __int64 dp[Maxn][1<<Maxn]; int num[1<<Maxn],cnt1,cnt2,graphic[Maxn],co,n,m; void dfs(int j,int f) { int i; if(j==m) { int sum=0; if(f) graphic[j]=1; else graphic[j]=0; for(i=m;i>=1;i--) sum+=graphic[i]*(1<<(m-i)); num[++cnt2]=sum; return ; } if(!f) { graphic[j]=0; dfs(j+1,0); graphic[j]=1; dfs(j+1,1); } else { graphic[j]=1; dfs(j+1,0); } } int main() { int i,j,k; while(scanf("%d%d",&n,&m)!=EOF,n||m) { if((n*m)%2) { printf("0
"); continue; } if(n==1) { printf("1
"); continue; } memset(dp,0,sizeof(dp)); graphic[0]=0; cnt2=0; dfs(1,0); for(i=1;i<=cnt2;i++) dp[1][num[i]]=1; int temp=1<<m; temp--; for(i=2;i<=n-1;i++) { for(j=1;j<=cnt2;j++) { for(k=0;k<=temp;k++) { if((k&num[j])==num[j]) { int now=temp-k; dp[i][now|num[j]]+=dp[i-1][k]; } } } } __int64 ans=0; for(j=1;j<=cnt2;j++) { for(k=0;k<=temp;k++) { if((k^num[j])==0) ans+=dp[i-1][k]; } } printf("%I64d
",ans); } return 0; }

 
 

좋은 웹페이지 즐겨찾기