UVa 11100 The Trip, 2007

今天的教训:做题要用大块的时间来做,上午做一下,做题做到一半就去忙别的事,那么后面再做的时候就无限CE,WA了。因为你很难或者需要很长时间来找回当时的思路。

题意:就像套瓷娃娃一样,有n个包,大小可能一样可能不一样,而且小的包只能被严格比它大的包包裹上。问如何打包,才能使总的包数最小,在这个前提下,还要使包裹的最多的那个包数量最少。

对这个题再抽象一次:有一个序列,要求将所有的元素划分成尽可能少的严格递增子序列,在这个前提下,最长子序列的长度尽可能少(也就是尽可能将这些元素平均分配到这些子序列中)。

分析

确定子序列的个数:子序列的个数就等于原序列中重复元素最多的次数

每个子序列的长度:假设原序列长度是n,子序列的个数是m。那么每个子序列的长度就是n/m 或 n/m + 1 (除法是向下取整)

如何尽量平均分配:将原序列从小到大排序后,从第一个元素开始,依次取后面的第m个元素,直到取到尽头,这是第一个子序列。第二个子序列就是从第二个元素开始取,以此类推。

保证元素的平均分配这是比较显然的了吧。

因为重复最多的才重复m次,所以元素a后面的第m个元素必定大于它,这保证了子序列的严格递增。

 1 //#define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7
 8 const int maxn = 1000000 + 10;
 9 int a[maxn], b[maxn];
10
11 int main(void)
12 {
13     #ifdef LOCAL
14         freopen("11100in.txt", "r", stdin);
15     #endif
16
17     int n;
18     bool flag = false;
19     while(scanf("%d", &n) == 1 && n)
20     {
21         int times = 0, i, j;
22         if(flag)    printf("\n");
23         flag = true;
24
25         memset(b, 0, sizeof(b));
26         for(i = 0; i < n; ++i)
27         {
28             scanf("%d", &a[i]);
29             ++b[a[i]];
30             times = max(times, b[a[i]]);
31         }
32
33         printf("%d\n", times);
34         sort(a, a + n);
35         for(i = 0; i < times; ++i)
36         {
37             for(j = i; j < n - times; j += times)
38                 printf("%d ", a[j]);
39             printf("%d\n", a[j]);
40         }
41     }
42     return 0;
43 }

代码君

时间: 2025-01-05 22:55:42

UVa 11100 The Trip, 2007的相关文章

UVA 11100 The Trip, 2007 水题一枚

题目链接:UVA - 11100 题意描述:n个旅行箱,形状相同,尺寸不同,尺寸小的可以放在尺寸大的旅行箱里.现在要求露在最外面的旅行箱的数量最少的同时满足一个旅行箱里放的旅行箱的数量最少.求出这样满足要求的任意一种方案. 算法分析:首先我们可以确定最少的旅行箱的数量cnt:即n个旅行箱里按照尺寸大小分类(尺寸相同的在同一类),数量最多的那一类的数量.然后把cnt看成有cnt个堆,第二个要求就是要让这cnt个堆里最大旅行箱数量最小,直接用vector处理即可. 等AC之后突然想到,三个旅行箱尺寸

UVa 11100 The Trip, 2007 (题意+贪心)

题意:有n个包,其中小包可以装到大的包里,包的大小用数字进行表示,求最小的装包数量. 析:这个题的题意不太好理解,主要是有一句话难懂,意思是让每个最大包里的小包数量的最大值尽量小,所以我们就不能随便输出了, 我们先求出最少多少包,这个肯定是相同包的的最大数目了,然后输出时用等差输出,这样就能保证题目的要求. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #inc

11100 - The Trip, 2007

题目:11100 - The Trip, 2007 题目大意:给出n个包,大包可以套小包,要求要最后的包的数目最小,任意给出一种组合方式即可. 解题思路:相同大小的包的数目决定了最后剩余的包的数目. 将这些包排成有序的,这样就是一个递增的序列,保证分组后同一组中后面的包一定比前一个大一些.总共m组,输出的时候只要每隔m个数输出一个数. 代码: #include <stdio.h> #include <string.h> #include <algorithm> usin

UVA11100- The Trip, 2007

题目链接 题意:给定n个正整数,把它们划分成尽量少的严格递增序列(前一个数必须小于后一个数),输出序列个数的最小值k和这k个序列. 思路:出现次数最多的个数就是序列的个数.输出比较麻烦,但我们只要每k个数输出一个数字,那么最后就可以将所有序列都输出来了. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; cons

The trip(Uva 11100)

题目大意: 给出n个数,要求将其分成最少的递增序列,保证序列最少的同时要使得序列长度的最大值最小.  n<=10000 题解: 1.我是直接看着<训练指南>里的中文题面的,lrj似乎忘记提“保证序列最少的同时要使得序列长度的最大值最小”这个条件了,WA到死..我的做法是统计每个数出现的次数,然后每次尽可能构造一个最长的序列,这样能保证序列个数最少,但是显然不满足第二个条件. 2.由于之前WA到死,就很没志气的百度了题解..然后瞄到一眼最少的序列个数就是出现次数最多的那个数的出现次数(记为

UVa 11100 旅行2007

https://vjudge.net/problem/UVA-11100 题意: 给定n个正整数,把它们划分成尽量少的严格递增序列,尽量均分. 思路: 因为必须严格递增,所以先统计每个数字出现的次数,次数最多的就是要划分的序列个数. 接下来每次用最多次数作为步长划分,很巧妙. 1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<algorithm> 5 #include

Uva 网络(Network,Seoul 2007,LA 3902)

1 #include<iostream> 2 #include<cstring> 3 #include<vector> 4 using namespace std; 5 6 const int maxn=1000+10; 7 int n,s,k; 8 vector<int> tree[maxn],nodes[maxn]; 9 int fa[maxn]; 10 bool covered[maxn]; 11 12 void dfs(int u,int f,int

uva--11100The Trip, 2007

题意: 现在有n个不同容量的包,他们的容量用数字表示:规定小的包可以嵌套进大的包里去(但每个包只能嵌套一个包),这样安排才可以使得最后需要提的包的数目最少;在保持包的数目最少的同时,也需要使得每一个大包里面装的小包最大数目数目尽量少. 思路: 开始的时候一直没想清楚最后最少的包数应该是多少:后面灵光一闪,突然就发现最后可以保留的最少包数应该就是数目最多的那种包的个数(记为cnt).想清楚这一点后,就要考虑题目中要求的大包中装的小包数尽量少的问题了,为了达到这个目的我们可以使得每个包中装的小包数尽

思维专题(不定期更新)

1.UVa 11100 - The Trip, 2007 题意:给出若干大小不同的包裹,小的能够装在大的包裹里面.求最小的大包裹数,并且保证在所有的大包裹中,所含有的小包裹数目最小. 思路:显然,相同大小的包只能放在不同的大包里,那么最小的大包数目就是相同大小的包的最大数目,记为k.之后,根据从小到大排序后,对于每个大包i可选取从i开始,间隔k个包的那些包裹作为该大包从里到外的各个包裹. 1 #include<iostream> 2 #include<algorithm> 3 us