第一部分:题目
心急的C小加 题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=236
时间限制:1000 ms | 内存限制:65535 KB
难度:4
- 描述
-
C小加有一些木棒,它们的长度和质量都已经知道,需要一个机器处理这些木棒,机器开启的时候需要耗费一个单位的时间,如果第i+1个木棒的重量和长度都大于等于第i个处理的木棒,那么将不会耗费时间,否则需要消耗一个单位的时间。因为急着去约会,C小加想在最短的时间内把木棒处理完,你能告诉他应该怎样做吗?
- 输入
- 第一行是一个整数T(1<T<1500),表示输入数据一共有T组。
每组测试数据的第一行是一个整数N(1<=N<=5000),表示有N个木棒。接下来的一行分别输入N个木棒的L,W(0 < L ,W <= 10000),用一个空格隔开,分别表示木棒的长度和质量。 - 输出
- 处理这些木棒的最短时间。
- 样例输入
3 5 4 9 5 2 2 1 3 5 1 4 3 2 2 1 1 2 2 3 1 3 2 2 3 1
- 样例输出
- 2
- 1
- 3
- 第二部分:思路
- 这题贪心的角度就是:尽量一次能够连续处理最多的木棒。那么这些木棒必须满足条件:后面的木棒的长度和重量必须大于等于前一个。怎么样能够得到最大值呢?先对长度或者重量进行从大到小排序,那么再看另一个数值是否满足条件即可。可是这题必须是先对长度进行排序,然后看重量(这就是这题的问题所在)。就相当于把这些木棒进行分组,每组按照长度从小到大排序,重量必须是非减序列。
- 处理的过程就是:小的先进行处理,后面只要是满足重量不小于前一个木棒就可以继续处理。也就是按照长度从小到大排序后,重量有多少个增序列?需要注意的是:在对长度进行排序时,如果长度相等,进一步对重量进行大小排序。因为数据量原因,排序使用快排。有需要的百度吧。
- 第三部分:代码
-
#include<stdio.h> int fun(int v[100][2], int left, int right)//快速排序 { if(left < right) { int key = v[left][0]; int key2= v[left][1]; int low = left; int high = right; while(low < high) { while(low < high && v[high][0] >= key) { if(v[high][0]==key&&v[high][1]<key2)//在长度相同的情况下再对重量进行排序 { int t=v[high][1]; v[high][1]=key2; key2=t; v[low][1]=t; } high--; } v[low][0]= v[high][0]; v[low][1]= v[high][1]; while(low < high && v[low][0]<= key) { if(v[low][0]==key&&v[low][1]>key2) { int t=v[low][1]; v[low][1]=key2; key2=t; v[high][1]= key2; } low++; } v[high][0]= v[low][0]; v[high][1]= v[low][1]; } v[low][0]= key; v[low][1]= key2; //注意:递归条件 if(low-1>left) { fun(v,left,low-1); } if(low+1<right) { fun(v,low+1,right); } } } int main() { int n,m,i,len; int s[5001][2]; scanf("%d",&n); while(n--) { scanf("%d",&len); for(i=1;i<=len;i++) { scanf("%d %d",&s[i][1],&s[i][0]);//存储木棒的长和重量 } fun(s,1,len); int count=0;//记录排序后的重量的增序列个数 for(i=1;i<=len;i++) { if(s[i][1]==0)//如果一个数在一个增序列中用过了就置为0 { continue; } int j; count++; int temp=s[i][1]; s[i][1]=0; for(j=i+1;j<=len;j++) { if(s[j][1]>=temp) { temp=s[j][1]; s[j][1]=0; } } } printf("%d ",count); } return 0; }