【Link】:

【Description】



有n(1≤n≤50)堆盘子,第i堆盘子有hi个盘子(1≤hi≤50),从上到下直径不减。所有盘 子的直径均不超过10000。有如下两种操作。

split:把一堆盘子从某个位置处分成上下两堆。

join:把一堆盘子a放到另一堆盘子b的顶端,要求是a底部盘子的直径不超过b顶端盘子 的直径。

你的任务是用最少的操作把所有盘子叠成一堆

【Solution】



假设我们进行了x次split操作;



我们总共需要的操作次数为x+x+n-1

因为进行一次split操作,连通块的个数就会递增1;

进行x次的话,就有x+n块;

然后把这x+n块合并成一块的话;

需要x+n-1次join操作;

再加上x次split操作;

总共就是2*x+n-1次操作;

然后我们考虑最后所有的方块都叠成了一块的情形

假设,我们一开始把n堆的每一堆都染成同一种颜色;

则最后只剩一堆方块的时候,肯定是不同颜色相间的;

设最后只剩一堆方块的时候,上下相邻的单个方块之间,颜色不同的对数为cnt;

答案就为2*cnt-n+1

为什么不是上面分析的2*x+n-1次操作?

因为这里的cnt并不是分离的次数;

想一想,如果没有进行分离操作,直接全部叠在一个上面,肯定也有n-1个对是不相等的颜色;

则我们求出的cnt如果想变成分离的次数应该减去2*(n-1)

即2*(cnt-2*(n-1))+n-1 = 2*cnt-n+1

这样,就能根据最后答案的那一叠方块知晓答案了;

这可以给我们的DP提供思路;

我们就对最后的答案的那一堆进行DP;

在DP之前;

我们先将所有的盘离散化一下;

因为盘的直径最大达到了10000;

直接枚举盘的直径可能会跨了很多;

而盘子的数目最多为2500

然后,同一堆里的盘子,如果它的直径是一样的,那就把它们都当成一个盘子就好了;

之后;

考虑最后的答案构成的一堆盘子;

肯定是从上到下,盘子的直径不下降的;

则我们,从上到下,依次枚举每个盘子,它要放在哪一堆上面;

设f[i][j]表示,直径小于等于i(已经离散化过)的盘子,把它们都放到第j堆盘子上,最小的相邻不同颜色对数;

对于f[i][]这个状态肯定是移动到已经有i这个盘子的堆上比较划算;

设为j

则转移的时候;

只要找有i-1这个盘子的堆k;

然后用f[i-1][k]这个状态转移到f[i][j]

算一下会增加多少个相邻不同颜色就好;

转移的过程实际上就是其他i盘子移动到那个j上,以及k那一堆i-1盘子之上的整个移动到i上面来

(注意如果k那一堆的i-1盘子下面是i盘子的话,可以省掉一个不同的对数)

j和k相不相同要分类讨论,因为是两种情况;

因为允许放在“空地”上,所以j和k相同的情况也是ok的;

这比汉诺塔的更“自由”一点;

最后在f[cnt][1..n]中找最小值;



【NumberOf WA】



5



【Reviw】



按照递增的顺序枚举i;

看看1..i这一些盘子在哪一堆上面;

在哪一堆的情况都枚举一下;

就能得到所有的情况了;

主要是先想到,每个相邻的颜色不同的对数决定了最后答案;



【Code】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)
#define ri(x) scanf("%d",&x)
#define rl(x) scanf("%lld",&x)
#define rs(x) scanf("%s",x+1)
#define oi(x) printf("%d",x)
#define ol(x) printf("%lld",x)
#define oc putchar(' ')
#define os(x) printf(x)
#define all(x) x.begin(),x.end()
#define Open() freopen("F:\\rush.txt","r",stdin)
#define Close() ios::sync_with_stdio(0) typedef pair<int,int> pii;
typedef pair<LL,LL> pll; const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 2500;
const int M = 50;
const int INF = 0x3f3f3f3f; int n,have[M+10][N+10],a[M+10][M+10],b[N+10],cnt;
int f[N+10][M+10];
vector <int> v[N+100]; int main(){
//Open();
//Close();
int kk = 0;
while (~ri(n)){
ms(f,INF),ms(have,0);;
cnt = 0;
rep1(i,1,N) v[i].clear();
rep1(i,1,n){
ri(a[i][0]);
rep1(j,1,a[i][0]) {
ri(a[i][j]);
b[++cnt] = a[i][j];
}
a[i][0] = unique(a[i]+1,a[i]+1+a[i][0])-a[i]-1;
} sort(b+1,b+1+cnt);
cnt = unique(b+1,b+1+cnt) - b - 1; rep1(i,1,n){
rep1(j,1,a[i][0]){
int x = lower_bound(b+1,b+1+cnt,a[i][j]) - b;
have[i][x] = 1;
v[x].pb(i);
}
} int len = v[1].size();
rep1(i,0,len-1)
f[1][v[1][i]] = len-1; rep1(i,2,cnt){
int lenj = v[i].size(),lenk = v[i-1].size();
rep1(jj,0,lenj-1){
int j = v[i][jj];
rep1(kk,0,lenk-1){
int k = v[i-1][kk];
if (j!=k)
f[i][j] = min(f[i][j],f[i-1][k] + (int) v[i].size() -
(have[k][i]?1:0));
else{
int cost;
if ( (int) v[i].size() == 1)
cost = 0;
else
cost = (int) v[i].size();
f[i][j] = min(f[i][j],f[i-1][k] + cost);
}
}
}
}
int ans = INF;
rep1(i,1,n)
ans = min(ans,f[cnt][i]);
os("Case ");oi(++kk);os(": ");oi(ans*2-n+1);puts("");
}
return 0;
}

【Uva 1289】Stacking Plates的更多相关文章

  1. 【巧妙算法系列】【Uva 11464】 - Even Parity 偶数矩阵

    偶数矩阵(Even Parity, UVa 11464) 给你一个n×n的01矩阵(每个元素非0即1),你的任务是把尽量少的0变成1,使得每个元素的上.下.左.右的元素(如果存在的话)之和均为偶数.比 ...

  2. 【贪心+中位数】【UVa 11300】 分金币

    (解方程建模+中位数求最短累积位移) 分金币(Spreading the Wealth, UVa 11300) 圆桌旁坐着n个人,每人有一定数量的金币,金币总数能被n整除.每个人可以给他左右相邻的人一 ...

  3. 【UVa 10881】Piotr's Ants

    Piotr's Ants Porsition:Uva 10881 白书P9 中文改编题:[T^T][FJUT]第二届新生赛真S题地震了 "One thing is for certain: ...

  4. 【UVa 116】Unidirectional TSP

    [Link]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  5. 【UVa 1347】Tour

    [Link]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  6. 【UVA 437】The Tower of Babylon(记忆化搜索写法)

    [题目链接]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  7. 【uva 1025】A Spy in the Metro

    [题目链接]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  8. 【Uva 11584】Partitioning by Palindromes

    [Link]:https://cn.vjudge.net/contest/170078#problem/G [Description] 给你若干个只由小写字母组成的字符串; 问你,这个字符串,最少能由 ...

  9. 【Uva 11400】Lighting System Design

    [Link]: [Description] 你要构建一个供电系统; 给你n种灯泡来构建这么一个系统; 每种灯泡有4个参数 1.灯泡的工作电压 2.灯泡的所需的电源的花费(只要买一个电源就能供这种灯泡的 ...

随机推荐

  1. Java Web乱码分析及解决方式(二)——POST请求乱码

    引言 GET请求的本质表现是将请求參数放在URL地址栏中.form表单的Method为GET的情况.參数会被浏览器默认编码,所以乱码处理方案是一样的. 对于POST请求乱码.解决起来要比GET简单.我 ...

  2. POJ 1035-Spell checker(字符串)

    题目地址:POJ 1035 题意:输入一部字典.输入若干单词. 若某个单词能在字典中找到,则输出corret.若某个单词能通过 变换 或 删除 或 加入一个字符后.在字典中找得到.则输出这些单词.输出 ...

  3. hadoop MR 任务 报错 &quot;Error: java.io.IOException: Premature EOF from inputStream at org.apache.hadoop.io&quot;

    错误原文分析 文件操作超租期,实际上就是data stream操作过程中文件被删掉了.一般是由于Mapred多个task操作同一个文件.一个task完毕后删掉文件导致. 这个错误跟dfs.datano ...

  4. Android的矩阵(一):ColorMatrix

    最近的学习过程中看到关于android色彩矩阵的内容,以前看到这部分内容,基本都是跳过的,没有认真细读. 自己给自己找的借口是: 1,大一学的矩阵内容早就忘的干干净净了,当时学的时候就很烦人,所以现在 ...

  5. 5.应用与模块(ng-app)

    转自:https://www.cnblogs.com/best/tag/Angular/ 自动载入启动一个AngularJS应用,声明了ng-app的元素会成为$rootScope的起点 每个HTML ...

  6. azkaban(安装配置加实战)

    为什么需要工作流调度系统 一个完整的数据分析系统通常都是由大量任务单元组成:shell 脚本程序,java 程序,mapreduce 程序.hive 脚本等 各任务单元之间存在时间先后及前后依赖关 ...

  7. Sqoop 数据导入导出实践

    Sqoop是一个用来将hadoop和关系型数据库中的数据相互转移的工具,可以将一个关系型数据库(例如:mysql,oracle,等)中的数据导入到hadoop的HDFS中,也可以将HDFS的数据导入到 ...

  8. Coderfroces 862 B . Mahmoud and Ehab and the bipartiteness

     Mahmoud and Ehab and the bipartiteness Mahmoud and Ehab continue their adventures! As everybody in ...

  9. BZOJ 4430 Guessing Camels

    Description Jaap, Jan, and Thijs are on a trip to the desert after having attended the ACM ICPC Worl ...

  10. CentOS 安装openssl

    https://blog.csdn.net/ydyang1126/article/details/72902113 安装环境: 操作系统:CentOS 7 OpenSSL Version:openss ...