HDU 1693(状态压缩 插头DP)
我们引用国家队2008年陈丹琦的大作——《基于连通性状态压缩的动态规划问题》,上面对于插头、轮廓线的概念有详细的解释,不再赘述。
我们使用一个三维数组,前两维表示所在的格子,后一维表示轮廓线的状况,值为方案数。
在每一行开始前,我们需要把上一行最右的轮廓线转换为这一行最左的轮廓线,因此执行一次左移操作(实际上轮廓线是进行了向右的一次滑动)
然后枚举所在单元格对每个轮廓线的影响 在论文中我们可以发现轮廓线总是包围一个格子的上部分和左部分 我们认为如果有通路与轮廓线重合则为1否则为0
因此很容易想象出来(当然也可以看论文)各个状态之间的转移关系 对于可通行的格子 分部分覆盖和全部覆盖以及全部不覆盖的情况讨论
对不可通行的格子必须将不可能的覆盖方案置为0 到最后的结果就是所求的方案了即dp[m][n][0]
感谢DK大牛的指导 本人5天来的苦思冥想终于得到了成果 1693 0ms 排行统计第一....
以下为本人代码:
using namespace std;
typedef __int64 LL;
LL dp[12][12][1<<12];
long hash[12][12];
int main()
{
long T;
long b=1;
scanf("%ld",&T);
while (T--)
{
long i,j,k,m,n;
scanf("%ld %ld",&m,&n);
for (i=1;i<=m;++i)
{
for (j=1;j<=n;++j)
{
scanf("%ld",&hash[i][j]);
}
}
dp[0][n][0]=1;
for (i=1;i<=m;++i)
{
long len=1<<n;
for (j=0;j<len;++j)
{
dp[i][0][j<<1]=dp[i-1][n][j];
}
for (j=1;j<=n;++j)
{
len=(1<<n<<1);
for(k=0;k<len;++k)
{
long p=1<<j;
long q=p>>1;
bool x=p&k;
bool y=q&k;
if (hash[i][j])
{
dp[i][j][k]=dp[i][j-1][k^p^q];
if (x!=y)
{
dp[i][j][k]+=dp[i][j-1][k];
}
}
else
{
if (x==0&&y==0)
{
dp[i][j][k]=dp[i][j-1][k];
}
else
{
dp[i][j][k]=0;
}
}
}
}
}
printf("Case %ld: There are %I64d ways to eat the trees.\n",b++,dp[m][n][0]);
}
return 0;
}
以下为DK大人的sample代码,我加上了注释:
using namespace std;
int mat[100][100];
__int64 dp[12][12][1<<12];
int main()
{
// freopen("1.txt","r",stdin);
int zu;
int g=1;
scanf("%d",&zu);
while(zu--)
{
int m,n;
scanf("%d%d",&m,&n);
int i,j,k;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
scanf("%d",&mat[i][j]);
//memset(dp,0,sizeof(dp));
dp[0][n][0]=1;
for(i=1;i<=m;i++)
{
for(j=0;j<(1<<n);j++)
dp[i][0][j<<1]=dp[i-1][n][j];
//把最右边的去掉 把所有的状态拉到下一行并进行合理的改变(注意最左边的是低位所代表的数)
//上一行最右边的边格一定不与轮廓线重合 下一行最左边的边格也一定不与轮廓线重合
//所以进行的是上一行所有状态(也就是轮廓线)向右的一次滑动
for(j=1;j<=n;j++)//枚举决策线的拐向
{
for(k=0;k<(1<<n<<1);k++)//枚举轮廓线
{
int p=1<<j;//第j个轮廓段(上)
int q=p>>1;//第j-1个轮廓段(左)
bool x=k&p;//左轮廓是否与通路相交
bool y=k&q;//上轮廓是否与通路相交
//判断轮廓线在[i,j]为拐向时的分布 每个格子有1<<n<<1种 多阶段决策
if(mat[i][j])//如果该单元可以通行
{
dp[i][j][k]=dp[i][j-1][k^p^q];//必然有一个通路连接上一个格的通路
if(x!=y)
dp[i][j][k]+=dp[i][j-1][k];//有一处新覆盖则有另外的一种情况
}
else//否则为障碍格子
{
if(x==0&&y==0)//通路与轮廓线不相交
dp[i][j][k]=dp[i][j-1][k];//直接转移
else
dp[i][j][k]=0;//通路与轮廓线相交的方案一定为0
}
}
}
}
printf("Case %d: There are %I64d ways to eat the trees.\n",g++,dp[m][n][0]);
}
return 0;
}
转载于:https://www.cnblogs.com/zhuangli/archive/2008/09/04/1283753.html
HDU 1693(状态压缩 插头DP)相关推荐
- hdu 5067(状态压缩dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5067 解题思路:这道题开始想复杂了,想用bfs去求出最短距离,其实没必要,因为题目中没有阻碍关系,所以 ...
- HDU 1565 状态压缩
题意: 你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大.(n <= 20 ...
- 洛谷 P-4045 密码(AC自动机+状态压缩+数位DP+乱搞)
洛谷 P-4045 密码 记AC的第一道黑题! 题意:已知一段密码包含了一些字符串,然后求满足条件的密码有多少个,数量小于42时还得全部输出 思路: 一开始WA了两个点,不知道WA的什么,索性把读入的 ...
- TYVJ 2054 [Nescafé29]四叶草魔杖 最小生成树 状态压缩/背包DP
$ \rightarrow $ 戳我进TYVJ原题 [Nescafé29]四叶草魔杖 题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Local 题目背 ...
- hdu 5713(状态压缩DP)
要进行两次dp, 第一个,dp[i],1<=i<=(1<<n) 其中用i的二进制形式表示已选择的点. dp[i] 用来保存i中的点构成一个连通块,边集多少种可能. 转移方程: ...
- 洛谷 P2051 [AHOI2009]中国象棋 状态压缩思想DP
P2051 [AHOI2009]中国象棋 题意: 给定一个n*m的空棋盘,问合法放置任意多个炮有多少种情况.合法放置的意思是棋子炮不会相互打到. 思路: 这道题我们可以发现因为炮是隔一个棋子可以打出去 ...
- hdu 5434(状态压缩+矩阵优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5434 官方题解: 这个题用状态转移得到矩阵,再矩阵快速幂就可以了. 合体象的攻击范围是变少了的,我们可 ...
- ZOJ 3502 Contest 状态压缩 概率 DP
链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3502 1 #include <iostream> 2 # ...
- Acwing291. 蒙德里安的梦想:状态压缩dp
文章目录 题目分析 状态表示 状态转移 时间复杂度 题目链接 题目分析 题意重述:给定n*m的方格,看能分成多少个1 *2的小方块. 题目分析: 摆放方块的时候,先放横着的,再放竖着的.总方案数等于只 ...
最新文章
- 反转链表JAVA算法_链表反转算法
- GO语言中json与map的转换
- Python3网络爬虫快速入门实战解析(一小时入门 Python 3 网络爬虫)
- Python---堆里有16颗豆子,有两个玩家依次取豆
- python面向对象作业_python面向对象编程作业
- idea怎么更改推到github的路径_IDEA 拉取、上传、更新 项目到 Gitee+GitHub_超详细超简单版...
- char赋值字符串常量和数值的区别
- Flink从入门到入土
- Spring Framework--Data Access(1)--Transaction Management(2) - 声明式事务管理
- PL/SQL Developer 8注册码
- js使用闭包循环为a标签正确添加事件
- 最具有中国特色的脑筋急转弯
- 【python 作日期的折线图和柱状图组合图】
- 机器学习sklearn----支持向量机SVC模型评估指标
- SpringBoot分布式项目实现Session共享
- 麻辣烫有几种类型?不同种麻辣烫怎么做
- 香港等海外公司如何开通认证微信公众号?
- 加强【圣域2】各个技能的打击感-华丽的击飞效果
- Linux Shell 并行
- scite可以编程c语言不,SciTE中文使用步骤.doc