1. 程式人生 > >插頭dp

插頭dp

aps 連通性 nbsp pre http 連通 eat tree open

基於連通性的狀壓dp

經典入門例題:HDU 1693

Eat the Trees

代碼:

技術分享圖片
#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.\n",o,ans); } return 0; }
Eat the Trees

插頭dp