POJ 2411 Mondriaan's Dream 解题报告【动态规划】(代码部分)

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

 

long long dp[12][3000];

//用0代表横放或竖放的上部,1代表竖放的下部,每行是一个二进制数(<2048)

int main()

{

         long long h,w,ans,i,j,k,tmp1,tmp2,l,c,cs;

         scanf("%lld",&cs);

         while(cs--)

         {

                   scanf("%lld%lld",&h,&w);

                   if(h*w&1) {printf("0\n"); continue;}

                   if(w>h){tmp1=h; h=w; w=tmp1;}//h*2^w的数量级,因此让w为小的那个

                   memset(dp,0,sizeof(dp));

                   tmp1=w; l=1; while(tmp1--) l*=2;

                   for(i=0;i<l;i++)

                   {//得到第一行可能的情况,并赋值1

                            tmp1=i; c=w;

                            while(c)

                            {

                                     if(tmp1&1) tmp1>>=1,c--;

                                     else if(tmp1&3) break;

                                     else if(c<2) break;

                                     else tmp1>>=2,c-=2;

                            }

                            if(!c) dp[0][i]=1;

                   }

                   for(i=1;i<h;i++)

                   {//依次递推加和

                            for(j=0;j<l;j++)

                            {//对每行的每一个状态递加底层的相容状态

                                     for(k=0;k<l;k++)

                                     {//寻找相融状态并递加

                                               tmp1=j; tmp2=k; c=w;

                                               while(c)

                                               {

                                                        if(tmp2&1)

                                                        {

                                                                 if(tmp1&1) break;

                                                                 else tmp1>>=1,tmp2>>=1,c--;

                                                        }

                                                        else

                                                        {

                                                                 if(tmp1&1) tmp1>>=1,tmp2>>=1,c--;

                                                                 else if(c<2||(tmp1&3)||(tmp2&3)) break;

                                                                 else tmp1>>=2,tmp2>>=2,c-=2;

                                                        }

                                               }

                                               if(!c) dp[i][j]+=dp[i-1][k];

                                     }

                                     if(i==h-1) break;//最上层必全为0,找到为0的情况即是结果

                            }

                   }

                   printf("%lld\n",dp[h-1][0]);

         }

         return 0;

}

posted on   liugoodness  阅读(604)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述

导航

< 2010年3月 >
28 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 1 2 3
4 5 6 7 8 9 10

统计

点击右上角即可分享
微信分享提示