题目描述
某工厂生产一批棍状零件,每个零件都有一定的长度(Li)和重量(Wi)。现在为了加工需要,要将它们分成若干组,使每一组的零件都能排成一个长度和重量都不下降(若 i
输入
第一行为一个整数 N(N<=1000),表示零件的个数,第二行有 N 对正整数,每对正整数表示这些零件的长度和重量,长度和重量均不超过 10000。
输出
仅一行,即最少分成的组数。
样例输入
5
8 4 3 8 2 3 9 7 3 5
样例输出
2
分析:首先每一组必须满足两个条件,零件的长度和重量都是不下降的。如果同时考虑这两个条件的话,会比较麻烦,所以好的思想是先简化条件。
那么我们可以先按长度从小到大排序,然后按这个顺序给零件分组。这样每一组零件的长度一定是不下降的,只用考虑重量即可。
那关于重量该怎么处理呢?首先可定的是,如果当前的零件的重量小于该组最后一个零件的重量的话,那一定不能放在这一组了,必须放到另一个合法的组(或者新成立一组)。
但如果这个零件可以放到这一组呢?是直接放吗?那可不一定,比如下图
还有(6, 7) 和 (7, 5) 没有放,如果(6, 7) 放到第一组的话,那么(7, 5) 就必须新开一组了。但是最优的方法是(6, 7) 放到第二组,(7, 5) 放到第一组,这样总共就两组。
所以对于每一个零件,我们要放到重量和他最相近(但不能大于它)的零件上面,保证放完这个零件后所浪费的空间最少。(空间只是为了好说话,并不是严格意义上的空间)
具体代码的实现,因为题中说长度和重量均不超过 10000,那么就可以开一个数组记录每一组的最后一个零件的重量。然后对于每一个零件 i,从 w[i] 开始向 0 循环,若遇到一个vis[j] 被标记过,说明这有一组,且放完后浪费的空间一定最少,就 vis[j] --, vis[w[i]] ++, break,表示这一组的最后一个零件的重量变成了 w[i]。
1 #include
2 #include
3 #include
4 #include
5 #include
6 using namespacestd;7 #define rep(i, a, n) for(int i = a; i <= n; ++i)
8 #define per(i, n, a) for(int i = n; i >= a; --i)
9 typedef long longll;10 const int maxn = 1e3 + 5;11 const int max_num = 1e4 + 5;12
13 structNode14 {15 intl, w;16 bool operator < (const Node& other)const
17 {18 return (l < other.l) || (l == other.l && w <=other.w);19 }20 }a[maxn];21 intn, vis[max_num];22 int ans = 0;23 intmain()24 {25 freopen("stick.in", "r", stdin);26 freopen("stick.out", "w", stdout);27 scanf("%d", &n);28 rep(i, 1, n) scanf("%d%d", &a[i].l, &a[i].w);29 sort(a + 1, a + n + 1);30 rep(i, 1, n)31 {32 per(j, a[i].w, 0)33 if(vis[j]) {vis[j]--; break;}34 vis[a[i].w]++;35 }36 rep(i, 1, max_num - 1) if(vis[i]) ans++; //数一数有多少组
37 printf("%d\n", ans);38 return 0;39 }