ACM - ICPC World Finals 2013 H Матрёшка
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf
题目翻译:
问题描述
俄罗斯套娃是一些从外到里大小递减的传统的俄罗斯木头玩偶组成的。当你打开一个俄罗斯套娃时,里面就会露出一个同样的俄罗斯套娃,再打开,就会再露出一个,不断重复。
俄罗斯的俄罗斯套娃博物馆最近收藏了一些外形相似的俄罗斯套娃集,只是里面嵌套的玩偶数量不相等。不幸的是,有一群过分热情的(和明显无人监督的)孩子们拆了他们,并放在一行上。有n个玩偶在一上,每个都有一个整数的大小,你需要重新组装套娃集,你既不知道套娃集的数量,也不知道某个套娃集内玩偶的数量,你只知道一个完好的套娃集内的玩偶大小是从1到某个数字m
在组装套娃集时,你必须遵守下列规则:
1.你只能将一个玩偶或者套娃集放入一个更大的玩偶中
2.你只能把相邻两个俄罗斯套娃组合在一起
3.已经被合并的玩偶是不能再重新拆出来的。
你的时间很宝贵,你只想尽快的组装好。唯一需要耗时的部分为打开一个玩偶并马上关上它。所以你要尽可能少的做这种操作。比如说:合并[1,2,6]与[4],你需要将大小为4和6的两个玩偶拆开。合并[1,2,5]与[3,4]代价为3。
求将n个玩偶重新拼成一些完好的俄罗斯套娃的最小代价。
输入格式
第一行一个数n,第二行包含n个数,依次表示每个玩偶的大小。
输出 格式
如果答案存在,输出一个数表示将n个玩偶重新拼成一些完好的俄罗斯套娃的最小代价。否则输出“Impossible”
样例输入
7
1 2 1 2 4 3 3
样例输出
Impossible
样例输入
7
1 2 3 2 4 1 3
样例输出
7
数据规模和约定
1<=n<=500 , 1<=玩偶大小<=500
题目大意:
有n个套娃排成一列,我们要将它们合并成若干个完整的套娃(即这个套娃的最大一层为m,它里面包含从1~n-1所有大小的套娃各一个),每次只能选择相邻两个合并,且已经合并的套娃不可以拆开(在与其它套娃合并时可以临时拆开),问完成合并至少需要将套娃拆开多少次(例如将(3, 2)与(1)合并需要拆开两次)
思路分析:
这是一道区间DP的题目,看到数据范围和时间限制,大概是一个\(O(n^3)\)左右的复杂度。我们先预处理出\(g(i,\,j)\),表示将序列上的第i个套娃到第j个套娃合并成一个套娃(不需要是完整的套娃)需要拆开的最小次数。显然当i~j中存在相同大小的套娃时,\(g(i,\,j)=\infty\)(他们不可能被合并成一个)
我们可以轻松写出转移方程\[g(i,\,j)=\max_{(i\le k<j)}{\left\{g(i,\,k)+g(k+1,\,j)+f(i,\,k,\,j)\right\}},\]其中这个\(f(i,\,k,\,j)\)表示将合并完的(1~k)和(k + 1~j)合并起来所需的最小代价。通过观察可以发现我们不需要把两边的所有套娃全都拆开,但是至少要将一边的套娃全部拆开,而另一边只要拆到剩下的那一组套娃正巧可以放到完全拆开的那一组的最小的那一个套娃里面就好了,这等价于将求出两组套娃中的分别的最小值的较大者,小于这个较大者的套娃全部不用拆开而剩余的(包括这个较大者都需要拆开)。至此我们已经得到了\(f(i,\,k,\,j)\)的计算方法,然后\(g(i,\,j)\)就已经搞定了
接下来我们定义\(p(k)\)表示将前k个合并成若干个(多少个?不需要知道)完整的套娃需要的最小拆开次数,然后得到转移方程\[p(k)=\min_{1\le i<k}{\{p(i)+g(i+1,\,k)\}},\]然后就解决了。
算法流程:
1.DP计算\(g(i,\,j)\),在计算过程中对i~j进行局部排序,之后枚举k,并同时分别维护1~k与k+1~j中的最小值,然后计算得到解
在这里我有一点要说明的,排序的时候我建议使用计数排序,有两个原因:首先,套娃大小的范围与n的范围是相同的,使用计数排序可以保证渐进复杂度为线性,而快排之类的就会退化成\(O(n\log n)\)。第二,更重要的是,计数排序更容易维护每一个值的名次(否则需要二分查找,又是一个log)。
2.DP计算\(p(k)\)
3.\(p(n)\)即为所求
参考代码:
//date 20140123
#include <cstdio>
#include <cstring> const int maxn = ;
const int INF = ; inline int getint()
{
int ans(); char w = getchar();
while(w < '' || w > '')w = getchar();
while('' <= w && w <= '')
{
ans = ans * + w - '';
w = getchar();
}
return ans;
} inline int max(int a, int b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;} int n;
int a[maxn];
int count[maxn], count2[maxn];
int sum[maxn];
int exist[maxn];
int g[maxn][maxn];
int f[maxn]; inline int check(int l, int r)
{
memset(exist, , sizeof exist);
for(int i = l; i <= r; ++i)if(exist[a[i]])return false;
else ++exist[a[i]];
for(int i = ; i <= r - l + ; ++i)if(!exist[i])return false;
return true;
} int main()
{
freopen("matryoshka.in", "r", stdin);
freopen("matryoshka.out", "w", stdout); n = getint();
for(int i = ; i <= n; ++i) a[i] = getint();
memset(g, 0x7F, sizeof g);
for(int i = n; i; --i)
{
g[i][i] = ;
for(int j = i + ; j <= n; ++j)
{
g[i][j] = INF;
int Max(), flag(), Min1(INF), Min2(INF), ans(INF), Min(INF);
memset(count2, , sizeof count2);
memset(count, , sizeof count); for(int w = i; w <= j; ++w)
if(count2[a[w]]){flag = ; break;}
else {++count2[a[w]]; ++count[a[w]]; Min2 = min(Min2, a[w]); Max = max(Max, a[w]);}
if(flag)continue;
sum[Min2 - ] = ; for(int w = Min2; w <= Max; ++w)sum[w] = sum[w - ] + count[w]; for(int k = i; k < j; ++k)
{
--count2[a[k]];
Min1 = min(Min1, a[k]);
if(Min2 == a[k])for(Min2; !count2[Min2]; ++Min2); ans = min(ans, g[i][k] + g[k + ][j] + (j - i + ) - sum[max(Min1, Min2) - ]);
}
g[i][j] = ans;
}
} f[] = ;
for(int i = ; i <= n; ++i)f[i] = INF;
if(a[] == )f[] = ;
for(int i = ; i <= n; ++i)
{
for(int j = ; j < i; ++j)
if(check(j + , i)){f[i] = min(f[i], f[j] + g[j + ][i]);}
} if(f[n] != INF) printf("%d\n", f[n]);
else printf("Impossible\n");
return ;
}
需要注意的事项:
1.在计算\(g(i,\,j)\)时,如果需要赋值成无穷大,不要直接使用INT_MAX,因为我们会出现一个相加比较,这样一加就导致无穷大变成了负数
2.一定要注意递推的顺序
3.计算\(g(i,\,j)\)的时候不建议使用递归,因为我们需要维护一个当前i~j的顺序,需要另开数组,如果开在全局变量则需要开很多,如果开在局部变量则容易爆栈
ACM - ICPC World Finals 2013 H Матрёшка的更多相关文章
- ACM - ICPC World Finals 2013 C Surely You Congest
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 试题来源 ACM/ICPC World Fin ...
- ACM - ICPC World Finals 2013 A Self-Assembly
原题下载 : http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 这道题其实是2013年我AC的第一道题,非常的开心,这 ...
- ACM - ICPC World Finals 2013 F Low Power
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 有n个机器,每个机器有2个芯片,每个 ...
- ACM - ICPC World Finals 2013 I Pirate Chest
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 海盗Dick受够了在公海上厮杀.抢劫 ...
- ACM - ICPC World Finals 2013 D Factors
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 一个最基本的算数法则就是大于1的整数 ...
- ACM - ICPC World Finals 2013 B Hey, Better Bettor
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 这题真心的麻烦……程序不长但是推导过程比较复杂,不太好想 ...
- [算法竞赛入门经典]Message Decoding,ACM/ICPC World Finals 1991,UVa213
Description Some message encoding schemes require that an encoded message be sent in two parts. The ...
- UVa210 Concurrency Simulator (ACM/ICPC World Finals 1991) 双端队列
Programs executed concurrently on a uniprocessor system appear to be executed at the same time, but ...
- 谜题 (Puzzle,ACM/ICPC World Finals 1993,UVa227)
题目描述:算法竞赛入门经典习题3-5 题目思路:模拟题 #include <stdio.h> #include <string.h> #define maxn 55 char ...
随机推荐
- SQL Server 监控 使用sp_trace_create
监控前言 上一节我们提到了MSSQL的基于SQL Event的监控,但是有些时候我们需要更加详细.适用于调优排错的监控.SQL Server内部运行的可见性是的查询调整.优化和综合排查成为可能!这一节 ...
- C#单链表(数据结构)
学习单链表的源码项目:http://files.cnblogs.com/xmfdsh/CSharp%E5%8D%95%E9%93%BE%E8%A1%A8.rar 链表是用一组任意的存储单元来存储线性表 ...
- Hello world,Hello 2015,Bye 2014
序 在我写下“在”这个字的时候已经是2014-12-31 19:59,14年最后一天了,总觉得不写点东西祭奠一下那些被自己虐死的脑细胞,心里就不舒服. 那就从生活,工作,学习三个方面,总结一下吧. 生 ...
- Long和Date数据类型之间相互转换代码
static final SimpleDateFormat DATETIME_SEC_STR = new SimpleDateFormat("yyyyMMddHHmmss"); 1 ...
- 3[doses] ------一种诡异的写法
在 head first c 的第60页,有这么一道题: 一个富翁因为服药过度而死亡. 下面是自动服药器的代码: #include <stdio.h> int main(void) { , ...
- HDU4776 Ants(Trie && xor)
之前mark下来的一道题,今天填一下坑. 题意是这样子的.给你一棵边上有权的树.然后有树上两点(u,v)的路径有n*(n-1)条,路径(u,v)的权值是边权的xor. 然后下面有m个询问,询问你n*( ...
- UITableView多选删除
设置一个在编辑状态下点击可改变图片的cell FileItemTableCell.h #import <UIKit/UIKit.h> @interface FileItemTableCel ...
- HDU 1116 || POJ 1386 || ZOJ 2016 Play on Words (欧拉回路+并查集)
题目链接 题意 : 有很多门,每个门上有很多磁盘,每个盘上一个单词,必须重新排列磁盘使得每个单词的第一个字母与前一个单词的最后一个字母相同.给你一组单词问能不能排成上述形式. 思路 :把每个单词看成有 ...
- mfc和win32区别
Win32通常是指sdk编程方法,app没有被封装,开发人员需要自己搭程序框架:mfC则是以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量 (整理 ...
- LevelDB系列之整体架构
LevelDb本质上是一套存储系统以及在这套存储系统上提供的一些操作接口.为了便于理解整个系统及其处理流程,我们可以从两个不同的角度来看待LevleDb:静态角度和动态角度.从静态角度,可以假想整个系 ...