ACM学习历程—HDU1584 蜘蛛牌(动态规划 && 状态压缩 || 区间DP)
Description
Input
每组数据有一行,10个输入数据,数据的范围是[1,10],分别表示A到10,我们保证每组数据都是合法的。
Output
Sample Input
Sample Output
题目要求是讲10张牌合并成一堆,然后小牌放在大小+1的大牌上。
这题关键是只有10张牌,那么每张牌在自己位置上,或者在其他位置上,那么设某一位为1表示牌在自己位置上,否则为0,这样就能进行状态压缩了。
p[state],state的二进制位就是每张牌的状态。p表示最优解
其次就是考虑到如果2不在自己位置上,3不在自己位置上,而4在自己位置上,那么234肯定在4的位置上,因为最多就是先3到4,然后2到3,或者先2到3,然后2、3一起到4(1不考虑的情况)
而且从中还能得到,某一位值为k的牌,可以放到k+1,k+2,k+3中第一个非0位置上。
这样状态更新就是
p[state^(1<<i)] = myMin(p[state^(1<<i)], p[state]+abs(i-j));(其中i是state的非0位,j是i以上第一个非0位)
myMin是自定义最小值,对第一个参数为-1的情况进行了特判,这里处理方式很多。
然后这个方程我不太会用for完成。用了spfa的思想前一个状态更新了会导致后面的状态更新。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#define LL long long using namespace std; int a[], p[], from;
int Hash[];
bool vis[]; int myMin(int x, int y)
{
if (x == -)
return y;
return min(x, y);
} void input()
{
memset(p, -, sizeof(p));
memset(vis, false, sizeof(vis));
from = ;
for (int i = ; i <= ; ++i)
{
scanf("%d", &a[i]);
Hash[a[i]] = i;
from |= (<<i);
}
p[from] = ;
} void spfa()
{
int k, v, pre;
queue<int> q;
q.push(from);
vis[from] = true;
while (!q.empty())
{
k = q.front();
q.pop();
vis[k] = false;
for (int i = ; i <= ; ++i)
{
if ((k & (<<i)) && a[i] != )
{
v = a[i]+;
while (!(k&(<<Hash[v])))
v++;
pre = p[k^(<<i)];
p[k^(<<i)] = myMin(p[k^(<<i)], p[k]+abs(i-Hash[v]));
if (p[k^(<<i)] != pre && !vis[k^(<<i)])
{
q.push(k^(<<i));
vis[k^(<<i)] = true;
}
}
}
}
} void work()
{
spfa();
printf("%d\n", p[<<Hash[]]);
} int main()
{
//freopen("test.in", "r", stdin);
int T;
scanf("%d", &T);
for (int times = ; times < T; ++times)
{
input();
work();
}
return ;
}
听了小烈的做法后@hqwhqwhq,发现可以用区间DP,这样n很大也可以解决了。
因为对于1到n这段连续的数,必然最后一次合并肯定是1~k移动到k+1~n上去。
那么自然可以枚举k来进行区间DP,需要注意的是DP若使用for循环,需要写成从小到大枚举区间长度来进行DP,否则需要记忆化搜索。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long using namespace std; const int maxN = ;
int n, a[maxN];
int p[maxN][maxN]; void input()
{
memset(p, -, sizeof(p));
scanf("%d", &n);
int k;
for (int i = ; i <= n; ++i)
{
scanf("%d", &k);
a[k] = i;
p[i][i] = ;
}
} inline int myMin(int x, int y)
{
if (x == -) return y;
else return min(x, y);
} void work()
{
for (int j = ; j < n; ++j)
for (int i = ; i+j <= n; ++i)
for (int k = i; k < i+j; ++k)
p[i][i+j] = myMin(p[i][i+j], p[i][k]+p[k+][i+j]+abs(a[k]-a[i+j]));
printf("%d\n", p[][n]);
} int main()
{
//freopen("test.in", "r", stdin);
int T;
scanf("%d", &T);
for (int times = ; times <= T; ++times)
{
input();
work();
}
return ;
}
ACM学习历程—HDU1584 蜘蛛牌(动态规划 && 状态压缩 || 区间DP)的更多相关文章
- 状态压缩---区间dp第一题
标签: ACM 题目 Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is ...
- ACM学习历程—HDU5586 Sum(动态规划)(BestCoder Round #64 (div.2) 1002)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5586 题目大意就是把一段序列里面的数替换成f(x),然后让总和最大. 首先可以计算出初始的总和,以及每 ...
- ACM学习历程——POJ1260 Pearls(动态规划)
Description In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces ...
- ACM学习历程—SNNUOJ1213 加油站问题(动态规划 || 数学)
题目链接:http://219.244.176.199/JudgeOnline/problem.php?id=1213 这是这次微软实习面试的一道题,当时只相出了一个2n的做法,面试官让我优化成n的做 ...
- ACM学习历程—CodeForces 176B Word Cut(字符串匹配 && dp && 递推)
Description Let's consider one interesting word game. In this game you should transform one word int ...
- ACM学习历程—HDU2476 String painter(动态规划)
http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意是给定一个起始串和一个目标串,然后每次可以将某一段区间染成一种字符,问从起始串到目标串最少需要染多 ...
- ACM学习历程—ZOJ3471 Most Powerful(dp && 状态压缩 && 记忆化搜索 && 位运算)
Description Recently, researchers on Mars have discovered N powerful atoms. All of them are differen ...
- HDU-1584 蜘蛛牌(dfs)
可以多看看. 蜘蛛牌 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU1584(蜘蛛牌)
蜘蛛牌 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
随机推荐
- 30:根据排序标识flag给数组排序
题目描述:输入整型数组和排序标识,对其元素按照升序或降序进行排序 接口说明 原型: void sortIntegerArray(Integer[] pIntegerArray, int iSortFl ...
- 分布式服务框架 Zookeeper(一)介绍
一.概述 ZooKeeper(动物园管理员),顾名思义,是用来管理Hadoop(大象).Hive(蜜蜂).Pig(小猪)的管理员,同时Apache Hbase.Apache Solr.LinkedIn ...
- Spark源码分析之一:Job提交运行总流程概述
Spark是一个基于内存的分布式计算框架,运行在其上的应用程序,按照Action被划分为一个个Job,而Job提交运行的总流程,大致分为两个阶段: 1.Stage划分与提交 (1)Job按照RDD之间 ...
- PHPExcel简易使用教程
在企业里使用PHP进行开发,不可避免总会遇到读/写Excel的需求,遇到这种需求,一般使用PHPExcel类库进行开发. PHPExcel现在最新版本是1.8.0,最低需要PHP5.2版本,支持读取x ...
- A20地址线问题
[0]README text description from Zhaojiong's perfect analysis of Linux kernel . [1]A20地址线问题(干货来了) 198 ...
- 离线安装Cloudera Manager5.3.4与CDH5.3.4(一)
这几天一直在安装CDH,头都搞大了,安装第三次,最终成功了. 第一次问题非常多.后面卸载了.由于没有卸载干净导致第二次安装失败. 后来索性重装系统了.直接使用了纯净系统进行安装.一个人跑到学院机房去装 ...
- Objective-C 内存管理之dealloc方法中变量释放处理
本文转载至 http://blog.sina.com.cn/s/blog_a843a8850101ds8j.html (一).关于nil http://cocoadevcentral.com/d/ ...
- VS2013 自动添加头部注释 -C#开发
在团队开发中,头部注释是必不可少的.但在开发每次新建一个类都要复制一个注释模块也很不爽,所以得想个办法让开发工具自动生成我们所需要的模板.....操作方法如下: 方法/步骤 1 找你的vs安装目录, ...
- 九度OJ 1011:最大连续子序列 (DP)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5615 解决:2668 题目描述: 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, N ...
- multiple-value uuid.NewV4() in single-value context
[root@t ~]# go get github.com/aliyun/aliyun-sts-go-sdk/sts# github.com/aliyun/aliyun-sts-go-sdk/sts/ ...