Stacking Plates UVA
来源:互联网 发布:sqlserver 字符串截取 编辑:程序博客网 时间:2024/06/05 20:10
题意:有n(1<=n<=50) 堆盘子,第i堆盘子有hi个盘子(1 <= hi <= 50),从上到下直径不减.所有盘子的直径均不超过10000。有如下两种操作.
split : 把一堆盘子从某个位置处分成上下两堆。
join:把一堆盘子a放到另一堆盘子b的顶端,要求是a底部的盘子的直径不超过b顶端盘子的直径.
你的任务是用最少的操作把所有盘子叠成一堆.
其实应该很容易想到,如果我们把不同的堆刷成不同的颜色。那么操作数就与最终状态的相邻异色对的数量ans有关 写几组数据后可以发现最终答案为2*ans-n+1。
那么 我们就可以把问题转化成为求最小异色对数。
如果定义dp[i][j] 为处理完半径小于等于i的圆盘 放在最下面的圆盘为第j种颜色。 这样定义的正确性和转移方程都很容易写。
但是因为i=10000 所以单次询问复杂度为O(10000*(n^2)) 再加上多组输入 数据变态一点(其实好像数据很弱,官方下载的数据全都是单组输入)很有可能超时。
然后因为最多只有2500个盘子 我们其实可以离散化一下。
然后就很(超)好(麻)写(烦)了。
WA了不知道多少发了 结果发现状态转移时没取最小值 ORZ。
代码写得很乱 没有可参考性
# include<iostream># include<cstdio># include<cstring># include<algorithm>#include<vector>#define mem(a,b) memset(a,b,sizeof a)using namespace std;int dp[2505][50];// dp[i][j]表示前i种直径的圆盘处理完后 第i种圆盘以第j堆结尾时的最小异色对数class node{public: int r,sum,id; bool operator < (const node & b) const { return r<b.r; }};bool judge[55][10005];vector<node> V[2505];node nodes[55][55];int hahs[2555];int blog[10005];int num[55];void init(){ mem(nodes,0),mem(judge,0),mem(dp,0x3f),mem(num,0); for(int i=0; i<2505; i++) V[i].clear();}int main(){ int n; int cases=0; while(~scanf("%d",&n)) { int tot=0; int T; init(); tot=0; for(int i=0; i<n; i++) { int sum; scanf("%d",&sum); int per=-1; int cnt; int len=0; for(int j=0; j<sum; j++) { scanf("%d",&cnt); judge[i][cnt]=1; if(cnt!=per) { per=cnt; hahs[tot++]=cnt; nodes[i][len].id=i; nodes[i][len].r=cnt; nodes[i][len].sum++; num[i]++; len++; } else { nodes[i][len-1].sum++; } } } sort(hahs,hahs+tot); tot=unique(hahs,hahs+tot)-hahs; for(int i=0; i<tot; i++) { blog[hahs[i]]=i; } for(int i=0; i<n; i++)// n堆 { for(int j=0; j<num[i]; j++)//每堆num[i]个元素 { int r=nodes[i][j].r; V[blog[r]].push_back(nodes[i][j]); } } for(int i=0; i<V[0].size(); i++) { dp[0][V[0][i].id]=V[0].size()-1; //printf("fuck:%d\n",dp[0][i]); } for(int i=1; i<tot; i++) { for(int j=0; j<V[i].size(); j++) { int id1=V[i][j].id;//代表当前圆盘属于第几堆 for(int k=0; k<n; k++)//k代表属于第几堆 { if(!judge[k][hahs[i-1]]) continue; /// dp[i][j]表示前i种直径的圆盘处理完后 第i种圆盘以第j堆结尾时的最小异色对数 if(id1!=k) { int cnt=V[i].size(); dp[i][id1]=min(dp[i-1][k]+cnt-(judge[k][V[i][j].r]),dp[i][id1]); } else { if(V[i].size()==1) dp[i][id1]=min(dp[i][id1],dp[i-1][k]); else dp[i][id1]=min(dp[i][id1],(int)(dp[i-1][k]+V[i].size())); } //printf("dp[%d][%d]=%d\n",i,id1,dp[i][id1]); } } } int ans=1<<30; for(int i=1; i<=n; i++) ans=min(dp[tot-1][i-1],ans); printf("Case %d: %d\n",++cases,2*ans-n+1); }}
阅读全文
0 0
- Stacking Plates UVA
- Uva-1289 Stacking Plates
- Uva-1289 Stacking Plates(DP)
- 20141005 【 DP 】 UVa 1289 Stacking Plates
- 【UVA1289】Stacking Plates
- UVa 12602 - Nice Licence Plates
- UVa 103 Stacking Boxes
- UVA 103 - Stacking Boxes
- uva 103 - Stacking Boxes
- uva 103 Stacking Boxes
- [UVA 103] Stacking Boxes
- UVa 103.Stacking Boxes
- uva:103 - Stacking Boxes
- UVa 103 - Stacking Boxes
- UVA - 103 Stacking Boxes
- uva 103 - Stacking Boxes
- UVA 103 Stacking Boxes
- UVa 103 - Stacking Boxes
- PowerDesigner的报表功能导出表的清单
- python进阶(8):常用模块2+异常处理
- 生成树个数(基尔霍夫矩阵)
- [编程题] 彩色的砖块
- 17、坐标移动(string转char[])
- Stacking Plates UVA
- 用telnet测试给163邮箱发邮件
- 使用intent在活动之间穿梭——使用显式Intent
- ROBOCON——TITR——2015回顾
- 关于Handler进行倒计时服务
- Checking an Alibi
- DOS命令于Mysql的基本用法
- setPriority()优先级
- Android程序员快速入门Objective-C ——Hello World