Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce
his score of the final test. And now we assume that doing everyone homework always takes one day. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework.. Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores.
3 3 3 3 3 10 5 1 3 1 3 1 6 2 3 7 1 4 6 4 2 4 3 3 2 1 7 6 5 4
0 3 5
题解:
这是团队赛比赛的一题,因为之前在做并查集和最小生成树的题,这题丢给了老刘,他也一遍过了,比完赛把这题补上,我也想了好一会,思路就是贪心,先把得到的数据按照数截止日期从小到大排序,如果相同按罚时从大到小排,然后把vis数组置为0,排好序后从前往后遍历,如果当前天数小于等于截止日期,就直接当前日期+1,否则,从已经加入套餐的中找到罚时比当前小的中最小的,记录下下标,找到了就把标记换成当前,以前的消掉,总罚时加上找到的那个的罚时,没找到直接加上当前罚时
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<string>
#include<stdio.h>
#include<queue>
#include<stack>
#include<map>
#include<deque>
using namespace std;
struct node
{
int d;
int p;
};
int cmp(node x,node y)//按截止日期从小到大排,如果相同就按罚时大的在前
{
if(x.d!=y.d)
return x.d<y.d;
return x.p>y.p;
}
node a[1005];
int vis[1005];//遍历数组
int main()
{
int test;
scanf("%d",&test);
while(test--)
{
int n;
scanf("%d",&n);
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
scanf("%d",&a[i].d);
for(int i=0;i<n;i++)
scanf("%d",&a[i].p);
sort(a,a+n,cmp);
int t=0,s=0;
for(int i=0;i<n;i++)
{
if(t<a[i].d)//如果小于等于当前天数,就直接标记下天数+1,因为是从0开始所以这里填小于
{
vis[i]=1;
t++;
}
else//不符合就先往前找已经加入套餐的有没有比这罚时更小的,有就找其中最小的
{
int b=i;
for(int j=i-1;j>=0;j--)
{
if(vis[j]&&a[j].p<a[b].p)//找最小的
{
b=j;//找到了记录下标
}
}
if(b!=i)//找到了
{
vis[b]=0;
vis[i]=1;
s+=a[b].p;
}
else//没找到
s+=a[i].p;
}
}
printf("%d\n",s);
}
return 0;
}