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 ...
随机推荐
- Smart Battery Specification Revision 1.1
1.SBS Specifications 2.System Management Bus (SMBus) Specification
- [Linux] 概念
操作系统包括: 内核:管理硬件资源 库:没有执行入口的程序,用于提升软件开发效率 应用程序:有执行入口的程序 常见库文件: windows系统:dll(dynamic link library)动态链 ...
- linux 更新yum源 改成163源
安装完CentOS6.3后,为避免从国外站点安装更新速度过慢,需要更改yum更新源,所以从网上找了下更改linux yum源的方法,和大家进行下分享.原理很简单,就是把yum配置文件中的更新源改一下, ...
- 高速修复汉澳sinox命令解释程序bash shell漏洞
bash是linux默认命令行管理程序shell.汉澳 sinox也安装有,尽管sinox并没有默认使用bash.可是用户一旦使用就会可能被通过漏洞入侵,所以必须高速修复.尽管sinox使用freeb ...
- ASP.NET动态网站制作(6)-- JS(1)
前言:JS的第一节课,在Visual Studio 2013中编写及运行.新建项目->Web->ASP.NET Web应用程序->Empty,打开后在项目下添加新建css文件夹和js ...
- ThinkPHP学习笔记(二)
1.比较好的参考手册(非官方,注意:也有一些错误,当出不来想要的效果时以官方的手册为准):http://www.5idev.com/p-thinkphp_lib_vendor.shtml 2.加载自定 ...
- Jquery和JS的区别
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 【BZOJ3864】Hero meet devil DP套DP
[BZOJ3864]Hero meet devil Description There is an old country and the king fell in love with a devil ...
- android菜鸟学习笔记17----Android数据存储(一)文件读写
假如有如下需求,要求能够记录用户输入的用户名和密码,下次登录时,能直接获取之前保存的用户名密码,并在相应的EditText中显示. 要保存用户输入的数据,最先想到的应该就是文件读写了. 通过对andr ...
- 为什么说Python是一门动态语言--Python的魅力
动态语言的定义:动态编程语言是高级程序设计语言的一个类别.在计算机科学领域已被广泛应用.它是一类在执行时能够改变其结构的语言:比如新的函数.对象.甚至代码能够被引进.已有的函数能够被删除或是其它结构上 ...