插头dp
Posted miracevin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了插头dp相关的知识,希望对你有一定的参考价值。
基于连通性的状压dp
经典入门例题:HDU 1693
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=11; int n,m; int mp[N+2][N+2]; int T; ll f[N+2][N+2][1<<(N+1)]; ll ans; void wrk(){ for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ for(int s=0;s<(1<<m+1);s++){ if(f[i][j][s]==0) continue; if(j!=m){// not a end //cout<<" here "<<i<<" "<<j<<" "<<s<<endl; int le=(s>>j-1)&1; int up=(s>>j)&1; if(mp[i][j]==0){ if(le==0&&up==0){ f[i][j+1][s]+=f[i][j][s]; } } else{ int now=s; if(le==1&&up==0){ int s0=s^(1<<j-1); s0|=(1<<j); f[i][j+1][s0]+=f[i][j][s]; f[i][j+1][s]+=f[i][j][s]; } else if(le==1&&up==1){ int s0=s^(1<<j-1); s0^=(1<<j); f[i][j+1][s0]+=f[i][j][s]; } else if(le==0&&up==1){ int s0=s^(1<<j); s0|=(1<<j-1); f[i][j+1][s0]+=f[i][j][s]; f[i][j+1][s]+=f[i][j][s]; } else{ int s0=s|(1<<j); s0|=(1<<j-1); f[i][j+1][s0]+=f[i][j][s]; } } } else{// j==m int le=(s>>j-1)&1; int up=(s>>j)&1; if(mp[i][j]==0){ if(le==0&&up==0){ f[i+1][1][(s<<1)]+=f[i][j][s]; } } else{ int now=s; //cout<<" irhf "<<i<<" "<<j<<" : "<<s<<" "<<le<<" "<<up<<endl; if(le==1&&up==0){ f[i+1][1][s<<1]+=f[i][j][s]; } else if(le==1&&up==1){ int s0=s^(1<<j-1); s0^=(1<<j); f[i+1][1][s0<<1]+=f[i][j][s]; } else if(le==0&&up==1){ int s0=s^(1<<j); s0|=(1<<j-1); f[i+1][1][s0<<1]+=f[i][j][s]; } else{ continue; } } } } } } } int main() { scanf("%d",&T); for(int o=1;o<=T;o++){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&mp[i][j]); } } ans=0; memset(f,0,sizeof f); f[1][1][0]=1; wrk(); /*for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ cout<<i<<" and "<<j<<" : "<<endl; for(int s=0;s<=(1<<m+1);s++){ cout<<" "<<s<<" |: "<<f[i][j][s]<<endl; } }*/ ans=f[n+1][1][0]; printf("Case %d: There are %lld ways to eat the trees. ",o,ans); } return 0; }
以上是关于插头dp的主要内容,如果未能解决你的问题,请参考以下文章