【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. 使用PXE+NFS EFI引导安装RHEL6/7以及Kickstart安装

    PXE引导的步骤: 1.开机后选择网络启动,client端向server端的dhcpd发起获取IP地址的dhcp请求. 2.server端分配IP后,dhcpd会同时根据其配置文件,通过TFTP协议发 ...

  2. whoami---打印当前有效的用户名称

    whoami命令用于打印当前有效的用户名称,相当于执行id -un命令. 语法 whoami(选项) 选项 --help:在线帮助: --version:显示版本信息. 实例 [root@localh ...

  3. C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件

    原文:C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件 这两天忙着把框架改为支持加载C++和Delphi的插件,来不及更新blog了.      原来的写的框架只支持c#插件,这个好做 ...

  4. ECNUOJ 2855 贪吃蛇

    贪吃蛇 Time Limit:1000MS Memory Limit:65536KBTotal Submit:480 Accepted:109 Description  相信很多人都玩过这个游戏,当然 ...

  5. error:assign attribute must be unsafeunretained

    今天在使用协议的过程中.偶然发现这样使用 ? 1 2 3 4 5 6 7 8 9 10 @interface AppDelegate (){     id<chatdelegate>  t ...

  6. Unity multiplayer

    using UnityEngine; using System.Collections; public class multiplayer_Button : MonoBehaviour { void ...

  7. Python数据可视化——散点图

    PS: 翻了翻草稿箱. 发现竟然存了一篇去年2月的文章...尽管naive.还是发出来吧... 本文记录了python中的数据可视化--散点图scatter, 令x作为数据(50个点,每一个30维), ...

  8. 字典(dictionary)与映射(map)

    1. 字典:key-value 键值对 反转字典:reverse_dict = dict(zip(D.values(), D.keys())) 前提要保证 D 的 value 不会出现重复,因为字典反 ...

  9. centos7 zabbix3.4.6显示中文乱码问题

    工具 : winscp (Linux Windows 传输文件工具) 当部署完zabbix然后显示中文会出现如下图 然后此时先去windows的文字目录如 C:\Windows\Fonts 随便托个字 ...

  10. HDU 1005 Number Sequence(矩阵)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...