hdu 1693 Eat the Trees——插头DP

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1693

第一道插头 DP !

直接用二进制数表示状态即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=15,M=(1<<12)+5;
int n,m,bin[N];ll dp[N][N][M];
int b[N][N];
void solve()
{
  int lm=m+1;
  bin[0]=1;for(int i=1;i<=lm;i++)bin[i]=bin[i-1]<<1;
  memset(dp,0,sizeof dp); dp[1][1][0]=1;
  for(int i=1;i<=n;i++)
    {
      for(int j=1;j<=m;j++)
    for(int s=0;s<bin[lm];s++)
      {
        if(!dp[i][j][s])continue;
        ll tp=dp[i][j][s];bool d0=s&bin[j-1],d1=s&bin[j];
        // ll tp not int tp!!!!!
        if(!b[i][j])
          {
        if(!d0&&!d1)dp[i][j+1][s]+=tp;
        continue;
          }
        int t=s^bin[j-1]^bin[j];
        if((d0&&d1)||(!d0&&!d1))
          dp[i][j+1][t]+=tp;
        if((d0&&!d1)||(!d0&&d1))
          dp[i][j+1][s]+=tp, dp[i][j+1][t]+=tp;
      }
      for(int s=0;s<bin[lm];s++)
    {
      if(!dp[i][lm][s]||s&bin[m])continue;
      dp[i+1][1][s<<1]+=dp[i][lm][s];
    }
    }
}
int main()
{
  int T; scanf("%d",&T);
  for(int t=1;t<=T;t++)
    {
      scanf("%d%d",&n,&m);
      for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      scanf("%d",&b[i][j]);
      solve();
      printf("Case %d: There are %lld ways to eat the trees.\n",
         t,dp[n][m+1][0]);
    }
  return 0;
}

 

posted on 2019-04-15 21:04  Narh  阅读(136)  评论(0编辑  收藏  举报

导航