【HDOJ】【1693】Eat The Trees

插头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 }
View Code(带注释)

 

转载于:https://www.cnblogs.com/Tunix/p/4272568.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值