1587: 做功课
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 21 Solved: 8
[ Submit][ Status][ Web Board]
Description
伊格内修斯刚刚参加完ACM/ ICPC比赛回来。现在,他有很多功课要做。每一位老师给他规定了功课提交的最后期限。
如果伊格内修斯的在截止日期后的递交作业,老师会减少他的最终测试得分。现在我们假设他每天都在做功
课。每门功课总是需要一天时间。现在,伊格请你帮他安排做功课,尽量减少降低分数的顺序。
Input
输入包含多个测试用例。输入的第一行是一个单一的整数t即测试用例的数目。
每个测试用例开始一个正整数N(1<= N <= 1000),其表示一共有多少门作业作业。接着两行数据。
第一行包含N个整数,表明该科目的最后期限,而下一行包含N个整数,表明了降低分数。
Output
对于每一个例子,你需要输出最少的可能降低的分数,每个测试占一行
Sample Input
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
Sample Output
0
3
5
【解析】
这道题就是叫我们求怎么让扣的分数最少,那肯定要用dp了,其实我dp也是菜鸡一个..网上模仿了大佬的算法,还是
要不断的去充实自己吧,言归正传,我们要求出总共要扣多少分数,然后我们求出我们最多能获得多少分数,然后用
本应该去扣的分数减去能获得的最大的分数就可以得到最少被扣到多少分了,这里我们用背包问题来求解,就是算第
j天最多能拿到多少分。需要注意的是这里读入的时间是最后的期限
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <iostream>
using namespace std;
struct E
{
int time;
int score;
}a[1001];
bool cmp(E b,E c)
{
if(b.time!=c.time)
return b.time<c.time;
return b.score>c.score;
}
int f[100010];
int main()
{
int t,i,j,n,sum,sum1;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
sum=0;
sum1=0;
memset(f,0,sizeof(f));
for(i=0;i<n;i++)
{
scanf("%d",&a[i].time);
}
for(i=0;i<n;i++)
{
scanf("%d",&a[i].score);
sum+=a[i].score;
}
sort(a,a+n,cmp);
for(i=0;i<n;i++)
{
for(j=a[i].time;j>0;j--)
{
f[j]=max(f[j],f[j-1]+a[i].score);//背包问题,求第j天能获得的最大分数
}
}
for(i=1;i<=a[n-1].time;i++)
{
sum1=max(sum1,f[i]);//求出最大的分数
}
printf("%d\n",sum-sum1);//所有的分数减去能获得的分数
}
return 0;
}