UVALive - 6434 (贪心)
题目链接:https://vjudge.net/problem/UVALive-6434
题意:给你n个数字,要你把这n个数字分成m组,每一组的消耗值定义为改组最大值和最小值之差,要求这m组的消耗值总和最小。
思路:既然我们要求把它分成m组,并且各组的最大值和最小值之差的和最小,我们就可以先把它分成n组,这时的总消耗值为零,我们为了让它的值尽可能的小,我们就可以每次选择两组使得总消耗值增加最少的
两组合并在一起,这时就只有n-1组了,重复以上操作n-m次,就可以得到分成m组所需的最小消耗了。(每次找寻使得总消耗增加最少的两组时,我们只要找到相邻的两组最大值和最小值差最小的就可以了)
假设当前 分组为(3,4)(7,8)
当我们要把这两组和并的时候,我们只要把总消耗值加上第二组的最小值和第一组的最大值的差就可以了,为什么可以这样呢?(当求一组数的最大值和最小值之差的和,不就可以看作是要把这组中的所有数字按照顺序连接在一起,每次连接的消耗
等于每两个相邻数字的差值,总和就是把他们全加其起来,例:(1,6,4,5,7,13,9),他们的最大值和最小值之差为12,不就等于先排序后(1,4,5,6,7,9,13),(4-1)+(5-4)+(6-5)+(7-6)+(9-7)+(13-9)=12 ,对于每组的连接也是相似的,只要把组看作单个数字就可以了
,只是它对于它前面一组的值是本组的最小值,对于后面一组的值为本组的最大值 )
我们可以看作把3,4和成一块消耗值为1,把7,8和成一块消耗值为1,这时3,4可以看作是一块,7,8可以看作是一块,当你要把3,4和7,8这两块连接在一起的时候,要增加的消耗不就是把4和7连接在一起的消耗吗。
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #define INF 1e9+5
- using namespace std;
- int s[110];
- int vt[110];//记录当前位置的数字是属于哪个集合的
- int main(){
- int t;
- int n,m;
- int i,j,k;
- int a,b,c;
- int mn;
- int nb=0;
- scanf("%d",&t);
- while(t--){
- nb++;
- scanf("%d%d",&n,&m);
- for(i=0;i<n;i++){
- scanf("%d",&s[i]);
- vt[i]=i;//分成n组
- }
- if(m==n)
- printf("Case #%d: 0\n",nb);
- else{
- sort(s,s+n);
- for(i=n;i>m;i--){
- mn=INF;
- a=vt[0];
- for(j=1;j<n;j++){
- if(vt[j]!=a){//两个分组的交界位置
- if(s[j]-s[j-1]<=mn){//找把两个集合合并在一起增加消耗最小的位置 ,一开始的思路只是找出合并后最大值和最小值之差最小的两个组进行合并
- //结果wa了一发,仔细想想后发现这样合并后并不能把增加的消耗值降到最小
- /*
- 1
- 10 2
- 1 5 6 7 8 9 10 13 13 13
- 当分组数位3的时候
- 此时分组为 (1) (5,6,7,8,9,10) (13,13,13)
- 如果只是单纯的把合并后最大值和最小值之差最小的两组合并的话,
- (1,5,6,7,8,9,10) (13,13,13)
- 此时总消耗为9
- (1) (5,6,7,8,9,10,13,13,13)
- 而最小的总消耗却是8
- 不能保证每次的增长量最小
- */
- c=j;//记录分界点
- mn=s[j]-s[j-1];
- }
- a=vt[j];//连接相邻的两个组的消耗一定是最小的
- }
- }
- /*for(j=0;j<n;j++){//不太理解的同学可以输出一下每次的分组情况便于理解
- printf("%d ",vt[j]);
- }
- printf("\n");*/
- int y=vt[c];
- for(j=c;vt[j]==y;j++){//合并
- vt[j]=vt[c-1];
- }
- }
- a=vt[0];
- b=0;
- long long sum=0;
- for(i=1;i<n;i++){
- if(vt[i]!=a){
- sum+=s[i-1]-s[b];//计算消耗值
- b=i;
- a=vt[i];
- }
- }
- sum+=s[n-1]-s[b];
- printf("Case #%d: %lld\n",nb,sum);
- }
- }
- return 0;
- }
- #include<stdio>
- #include<algorithm>
- using namespace std;
- int s[110]
- int main(){
- int t,n,m;
- int i,j,nb;
- nb=0;
- int a,b;
- scanf("%d",&t);
- while(t--){
- nb++;
- scanf("%d%d",&n,&m);
- for(i=0;i<n;i++){
- scanf("%d",&s[i]);
- }
- sort(s,s+n);
- for(i=0;i<n-1;i++)//直接记录下所有相邻的数字要合并在一起的消耗(这和上个代码的核心思想一致,但是
- //少了许多不必要的操作,直接记录下最核心的数据)
- s[i]=s[i+1]-s[i];
- sort(s,s+n-1);
- int sum=0;
- for(i=0;i<n-m;i++){//每次找到消耗代价最小的那一次合并
- sum+=s[i];
- }
- printf("Case #%d: %d",nb,sum);
- }
- return 0;
- }
UVALive - 6434 (贪心)的更多相关文章
- UVALive - 3266 (贪心) 田忌赛马
耳熟能详的故事,田忌赛马,第一行给出田忌的马的速度,第二行是齐王的马的速度,田忌赢一场得200,输一场失去200,平局不得也不失,问最后田忌最多能得多少钱? 都知道在故事里,田忌用下等马对上等马,中等 ...
- UVALive - 6434 (思维题)
题目链接:https://vjudge.net/contest/241341#problem/A 题目大意,给你n个数字,让你分成m组,每组的花费为每组的最大值-最小值,总的花费就是各组花费相加,要求 ...
- UVALive - 6434 —(思维题)
题意:给出了你由n个数组成的序列,让你将这个序列分为成m个集合,使得每一个集合的最大值减最小值的差相加最小.(如果某集合只有一个数字,则最大值减最小值为0) . 思路:首先我们不难想到,最优的分配方法 ...
- UESTC 2016 Summer Training #6 Div.2
我好菜啊.. UVALive 6434 给出 n 个数,分成m组,每组的价值为最大值减去最小值,每组至少有1个,如果这一组只有一个数的话,价值为0 问 最小的价值是多少 dp[i][j] 表示将 前 ...
- Gym 101194D / UVALive 7900 - Ice Cream Tower - [二分+贪心][2016 EC-Final Problem D]
题目链接: http://codeforces.com/gym/101194/attachments https://icpcarchive.ecs.baylor.edu/index.php?opti ...
- 贪心 UVALive 6834 Shopping
题目传送门 /* 题意:有n个商店排成一条直线,有一些商店有先后顺序,问从0出发走到n+1最少的步数 贪心:对于区间被覆盖的点只进行一次计算,还有那些要往回走的区间步数*2,再加上原来最少要走n+1步 ...
- 贪心 UVALive 6832 Bit String Reordering
题目传送门 /* 贪心:按照0或1开头,若不符合,选择后面最近的进行交换.然后选取最少的交换次数 */ #include <cstdio> #include <algorithm&g ...
- UVALive 7147 World Cup(数学+贪心)(2014 Asia Shanghai Regional Contest)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...
- UVALive 7146 Defeat the Enemy(贪心+STL)(2014 Asia Shanghai Regional Contest)
Long long ago there is a strong tribe living on the earth. They always have wars and eonquer others. ...
随机推荐
- 2.1 uml序言
UML Unified Modeling Language 统一建模语言 模型的定义 建模 modeling 重要的研发成果常常产自类比(analogy): 把不太理解的东西和一些已经较为理解.且十分 ...
- 邂逅明下 HDU - 2897
Problem description: 有三个数字n,p,q,表示一堆硬币一共有n枚,从这个硬币堆里取硬币,一次最少取p枚,最多q枚,如果剩下少于p枚就要一次取完.两人轮流取,直到堆里的硬币取完,最 ...
- 宽度优先搜索BFS(Breadth-First-Search)
Breadth-First-Search 1. 与DFS的异同 相同点:搜索所有可能的状态. 不同点:搜索顺序. 2. BFS总是先搜索距离初始状态近的状态,它是按照:开始状态->只需一次转移就 ...
- ubuntu chmod命令的使用
我推荐的地址:http://blog.163.com/bluesky_07_06_1/blog/static/164440083201161451735773/ 这个非常的牛逼.
- Leetcode 117
if(root == NULL) return; queue<TreeLinkNode *> que; que.push(root); while(!empty(que)){ int le ...
- 1004. Max Consecutive Ones III最大连续1的个数 III
网址:https://leetcode.com/problems/max-consecutive-ones-iii/ 参考:https://leetcode.com/problems/max-cons ...
- Linux系统下tomcat的配置
Linux系统下tomcat的配置 完成后可以输入命令查看日志文件: 最后进入网页测试下吧: 可以出来这个网页就好了
- mybatis标签之——<trim>及 <foreach collection>
https://www.cnblogs.com/zjfjava/p/8882614.html trim标记是一个格式化的标记,主要用于拼接sql的条件语句(前缀或后缀的添加或忽略),可以完成set或者 ...
- shiro过滤器解释类
anon -- org.apache.shiro.web.filter.authc.AnonymousFilter authc -- org.apache.shiro.web.filter.authc ...
- ubuntu分辨率
http://askubuntu.com/questions/235507/xconfig-xrandr-badmatch 先装驱动再说. 今天开机发现ubuntu分辨率不正常只有1024×768, ...