题目原文:http://acm.hdu.edu.cn/showproblem.php?pid=1789
题目大意:要在指定的日期内完成作业,并且每个作业只需要1天的时间并且每天只能做一个作业,没完成的就会扣相应的学分,要求被扣最少的学分。
题目分析:
起初我是这样想得:
1。如果在指定的日期内完成则不会扣分,且每个作业只需要一天完成,那么肯定会想到先把学分多的先做,是不是这样就能行呢,先看一组例子吧:
1 4 6 4 2 4 3
3 2 1 7 6 5 4
如果只考虑学分多的先做那么排列就会是:7654321 ,但这并不是最优的安排。
2。换个角度想了想,要使扣分少,我应该尽量使扣分少的过期在做,最好要让学分多的在它指定的那天完成,这样就会使得这天被扣分数尽量少。
结果思路就出来了: 1。先处理分数多的作业,把分数多的安排在它最后期限那一天。
2。如果那天被占用了,就往前一天安排。
3。如果前面没有日期了,就安排最后那天处理这个作业。此时就要扣掉对应的学分。
算法设计:1。利用STL中的sort()进行排序,但是因为定义了一个数据结构,需要重新写个判断函数。
2。定义一个vist[]数组来标记该天是否被安排
代码设计如下:
#include "iostream"
#include <algorithm> //need sort()
using namespace std;
struct Homwo //作页日期和分数的结构
{
int date;
int score;
}p[10002];
//以分数排名
bool cmp(const Homwo m,const Homwo n)
{
return m.score>n.score?1:0;
}
int main()
{
int t;
cin>>t;
while (t—)
{
int n;
int vist[10002]={0};
int flag,k=0;
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>p[i].date;
}
for (i=1;i<=n;i++)
{
cin>>p[i].score;
}
sort(p+1,p+n+1,cmp);//注意数组时从1开始的!按学分排列
for (i=1;i<=n;i++)
{
if(vist[p[i].date]==0) vist[p[i].date]=1;
else
{
for (int j=p[i].date-1,flag=0;j>0;j--)
{
if(vist[j]==0)
{ vist[j]=1;
flag=1;
break;
}
}
if (flag==0)
{
for (j=n;j>p[i].date;j--)
{
if(vist[j]==0)
{
vist[j]=1;
k=k+p[i].score;
break;
}
}
}
}
}
cout<<k<<endl;
}
return 0;
}