Description

蜘蛛牌是windows xp操作系统自带的一款纸牌游戏,游戏规则是这样的:只能将牌拖到比她大一的牌上面(A最小,K最大),如果拖动的牌上有按顺序排好的牌时,那么这些牌也跟着一起移动,游戏的目的是将所有的牌按同一花色从小到大排好,为了简单起见,我们的游戏只有同一花色的10张牌,从A到10,且随机的在一行上展开,编号从1到10,把第i号上的牌移到第j号牌上,移动距离为abs(i-j),现在你要做的是求出完成游戏的最小移动距离。
 

Input

第一个输入数据是T,表示数据的组数。
每组数据有一行,10个输入数据,数据的范围是[1,10],分别表示A到10,我们保证每组数据都是合法的。
 

Output

对应每组数据输出最小移动距离。
 

Sample Input

1
1 2 3 4 5 6 7 8 9 10
 

Sample Output

9

题目要求是讲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)的更多相关文章

  1. 状态压缩---区间dp第一题

    标签: ACM 题目 Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is ...

  2. ACM学习历程—HDU5586 Sum(动态规划)(BestCoder Round #64 (div.2) 1002)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5586 题目大意就是把一段序列里面的数替换成f(x),然后让总和最大. 首先可以计算出初始的总和,以及每 ...

  3. ACM学习历程——POJ1260 Pearls(动态规划)

    Description In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces ...

  4. ACM学习历程—SNNUOJ1213 加油站问题(动态规划 || 数学)

    题目链接:http://219.244.176.199/JudgeOnline/problem.php?id=1213 这是这次微软实习面试的一道题,当时只相出了一个2n的做法,面试官让我优化成n的做 ...

  5. ACM学习历程—CodeForces 176B Word Cut(字符串匹配 && dp && 递推)

    Description Let's consider one interesting word game. In this game you should transform one word int ...

  6. ACM学习历程—HDU2476 String painter(动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意是给定一个起始串和一个目标串,然后每次可以将某一段区间染成一种字符,问从起始串到目标串最少需要染多 ...

  7. ACM学习历程—ZOJ3471 Most Powerful(dp && 状态压缩 && 记忆化搜索 && 位运算)

    Description Recently, researchers on Mars have discovered N powerful atoms. All of them are differen ...

  8. HDU-1584 蜘蛛牌(dfs)

    可以多看看. 蜘蛛牌 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  9. HDU1584(蜘蛛牌)

    蜘蛛牌 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

随机推荐

  1. Oracle学习第三篇—多行函数

    0 order by asc/desc 默认升序 order by 列的名字|表达式|别名|序号 把空放在后边:order by desc nulls last 1分组函数--会自动滤空值 count ...

  2. opensearch空查询

    query子句不支持为空的查询,可以使用filter子句:filter=area=""   或者 filter=filedlen(area)=0 可以使用相关性函数实现:https ...

  3. Javaweb之 servlet 开发具体解释1

    1.1  Tip:Servlet简单介绍 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发 ...

  4. 1 zabbix3.2.4 安装

    一. 搭建zabbix服务 Zabbix 3.0对PHP的要求最低为5.4,而CentOS6默认为5.3.3,完全不满足要求,故需要利用第三方源,将PHP升级到5.4以上,注意,不支持PHP7.如下是 ...

  5. 【BZOJ4999】This Problem Is Too Simple! 离线+树状数组+LCA

    [BZOJ4999]This Problem Is Too Simple! Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2 ...

  6. EasyDSS高性能流媒体服务器前端重构(六)- webpack-dev-server 支持手机端访问

    很多时候,前端开发的页面,不仅要在PC端测试效果, 还要在手机端测试效果. 在开发阶段, 我们以 webpack-dev-server 来启动浏览器, 打开正在开发的页面. webpack-dev-s ...

  7. ajax学习笔记(3)--$.get()方法

    <head runat="server"> <title>jQuery中的$.get()方法</title> <script src=&q ...

  8. 九度OJ 1014:排名 (排序)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8267 解决:2469 题目描述:     今天的上机考试虽然有实时的Ranklist,但上面的排名只是根据完成的题数排序,没有考虑每题的分 ...

  9. 洛谷2483 k短路([SDOI2010]魔法猪学院)

    题目请戳这里 一句话题意: 给你一张n个节点,m条单向边的图,求1到n第k短的路. emmm,纪念第一个黑题(我是真的菜啊!!) 这题目还是很难的,本蒟蒻只会被洛谷卡掉的A(所以就愉快地特判了),首先 ...

  10. discuz论坛搬家

    很多站长第一次做网站的时候,无奈选择了速度不是很稳定的空间,慢慢会发现有很多物美价廉速度相当快的空间 这个时候,站长在网站搬家的过程中就会遇到很多困难,今天老袋鼠给大家详细讲解一下discuz论坛搬家 ...