zoukankan      html  css  js  c++  java
  • 【HDU1693】Eat the Trees-插头DP

    测试地址:Eat the Trees

    题目大意:一个N*M的矩形场地,有一些格子不能走,要求走若干条回路使得走过每个格子一次且仅一次,求方案数。

    做法:一看到棋盘类型的题目和很小的数据范围就想到插头DP。因为题目中要求若干条回路,所以轮廓线状态定义直接和骨牌覆盖问题一样,插头为1表示这个位置需要一个格子来承接,插头为0表示不需要。设f[i][j][state]为递推到第i行第j列的格子,轮廓线状态为state的方案数,逐格递推,枚举轮廓线状态,并找出第j和第j+1位(从左到右),称作关键位,判断:如果当前格子不能走,那么仅当两个关键位都为0时才更新状态,此时f[i][j][state]=f[i][j-1][state],否则f[i][j][state]=0。如果当前格子能走,按照关键位分成3种情况:两个关键位都为0,两个关键位都为1或者其中一个关键位为0,另一个关键位为1,分情况状态转移即可。和一般的插头DP问题一样,要注意递推到一行最后一个格子时轮廓线状态的转移。

    我傻逼的地方:轮廓线状态是m+1位的,所以数组要开到2^(m+1)那么多,而不是2^m......结果我交上去竟然提示TLE而不是RE,很迷......

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    using namespace std;
    int n,m,T,w[20][20],now,past;
    ll f[2][5010];
    
    int main()
    {
      scanf("%d",&T);
      for(int t=1;t<=T;t++)
      {
        memset(f,0,sizeof(f));
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	  for(int j=1;j<=m;j++)
    	    scanf("%d",&w[i][j]);
    	f[0][0]=1;
    	now=1,past=0;
    	for(int i=1;i<=n;i++)
    	  for(int j=1;j<=m;j++)
    	  {
    	    for(int k=0;k<(1<<(m+1));k++)
    		{
    		  int bit1=k&(1<<(j-1)),bit2=k&(1<<j);
    		  if (!bit1&&!bit2)
    		  {
    		    if (!w[i][j]) f[now][k]=f[past][k];
    			else f[now][k]=f[past][k+(1<<(j-1))+(1<<j)];
    		  }
    		  else if (!w[i][j]) {f[now][k]=0;continue;}
    		  else if (bit1&&bit2) f[now][k]=f[past][k-(1<<(j-1))-(1<<j)];
    		  else
    		  {
    		    if (bit1) f[now][k]=f[past][k]+f[past][k-(1<<(j-1))+(1<<j)];
    			else f[now][k]=f[past][k]+f[past][k-(1<<j)+(1<<(j-1))];
    		  }
    		}
    		if (j==m)
    		{
    		  for(int k=(1<<(m+1));k>=0;k--)
    		  {
    		    if (k%2) f[now][k]=0;
    			else f[now][k]=f[now][k>>1];
    		  }
    		}
    		swap(now,past);
    	  }
    	printf("Case %d: There are %lld ways to eat the trees.
    ",t,f[past][0]);
      }
      
      return 0;
    }
    


  • 相关阅读:
    用Python完成一个汇率转换器
    鸿蒙如何用JS开发智能手表App
    鸿蒙如何用JS开发智能手表App
    SAP Spartacus SplitViewComponent Migration 的一个具体例子
    SAP Spartacus B2B 页面 Popover Component 的条件显示逻辑
    SAP Spartacus 升级时关于 schematics 的更新
    SAP Spartacus B2B 页面 Disable 按钮的显示原理
    SAP Spartacus B2B 页面 Disable Confirmation 对话框的显示原理
    通过 Feature Level 动态控制 SAP Spartacus 的页面显示
    SAP Commerce Cloud Build Manifest Components
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793782.html
Copyright © 2011-2022 走看看