插头DP
插头dp模板题……
这题比CDQ论文上的例题还要简单……因为不用区分左右插头(这题可以多回路,并不是一条哈密尔顿路)
硬枚举当前位置的状态就好了>_<
题解:http://blog.csdn.net/xymscau/article/details/6756351
1 //HDU 1693 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #include<algorithm> 7 #define rep(i,n) for(int i=0;i<n;++i) 8 #define F(i,j,n) for(int i=j;i<=n;++i) 9 #define D(i,j,n) for(int i=j;i>=n;--i) 10 using namespace std; 11 int getint(){ 12 int v=0,sign=1; char ch=getchar(); 13 while(!isdigit(ch)) {if(ch==‘-‘) sign=-1; ch=getchar();} 14 while(isdigit(ch)) {v=v*10+ch-‘0‘; ch=getchar();} 15 return v*sign; 16 } 17 /*******************template********************/ 18 const int N=13; 19 typedef long long LL; 20 int mp[N][N]; 21 LL dp[N][N][1<<N]; 22 int n,m; 23 24 void DP(){ 25 memset(dp,0,sizeof (dp)); 26 dp[0][m][0]=1; 27 F(i,1,n){//第i行 28 // for(int j=0;j<(1<<m);j++) 29 rep(j,(1<<m)) 30 dp[i][0][(j<<1)]=dp[i-1][m][j]; 31 //换行(将上一行最后一格状态放到这一行第一格,方便转移……) 32 33 F(k,1,m)//第k个格子 34 rep(sta,1<<(m+1)){//枚举当前状态sta 35 int y=1<<k,x=1<<(k-1); 36 if(mp[i][k]){//如果当前格子无障碍 37 if( (sta&x)!=0 && (sta&y)!=0 )//如果状态为(1,1) 38 dp[i][k][sta]=dp[i][k-1][sta-x-y];//从(0,0)转移过来 39 else if( (sta&x)==0 && (sta&y)==0 )//如果状态为(0,0) 40 dp[i][k][sta]=dp[i][k-1][sta+x+y];//从(1,1)转移过来 41 else //状态为(0,1)或(1,0)则从(1,0)&&(0,1)转过来 42 dp[i][k][sta]=dp[i][k-1][sta^x^y]+dp[i][k-1][sta]; 43 }//如果当前格子有障碍 44 else 45 if( (sta&x)==0 && (sta&y)==0)//若当前状态为(0,0) 46 dp[i][k][sta]=dp[i][k-1][sta];//则ans从前一格 47 else 48 dp[i][k][sta]=0; 49 } 50 } 51 printf("There are %lld ways to eat the trees.\n",dp[n][m][0]); 52 } 53 int main(){ 54 int T=getint(),num=0; 55 while(T--){ 56 num++; 57 n=getint();m=getint(); 58 F(i,1,n) 59 F(j,1,m) mp[i][j]=getint(); 60 printf("Case %d: ",num); 61 DP(); 62 } 63 return 0; 64 }
(带注释)
时间: 2024-11-19 11:12:58