【HDU-1789】Doing Homework again

100 阅读1分钟
题意

主角打完ACM比赛回来,有一堆作业要做,每个作业有自己的deadline和score,如果不能在deadline之前完成就拿不到这个作业的分数,问主角最多能拿多少分

 

思路

按日期从小到大排,如果日期相同则按罚分从大到小排 按日期遍历,对应天数做对应期限的作业,如果期限重复了,就查找这一天之前的罚分最少的作业(回溯),如果这一天之前罚分最少的作业的罚分都比这一天作业的罚分大,则这一天就甘愿被罚掉。这一天就老老实实的做这个作业,然后再往后走

 

 

样例
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

 



 

AC代码
#include <iostream>
#include <algorithm>
using namespace std;
struct S
{
	int deadline;
	int reduce;
};
S x[1002];

bool cmp(S a, S b)
{
    if(a.deadline==b.deadline)
		return a.reduce>b.reduce;
	return a.deadline<b.deadline;
}
int main()
{
    int t,n,j;
    int vis[1002];
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(vis,0,sizeof(vis));   //vis每次初始化,并且要用这种方式来初始化,用“int vis[1002];”也不管
        
        for(int i=1;i<=n;i++)
            cin>>x[i].deadline;
        for(int i=1;i<=n;i++)
            cin>>x[i].reduce;
        sort(x, x + n+1, cmp);
        
/*      //检测排序结果
        cout<<endl;
        for(int i=1;i<=n;i++)
        {
            cout<<x[i].deadline<<" ";
        }
        cout<<endl;
        for(int i=1;i<=n;i++)
        {
            cout<<x[i].reduce<<" ";
        }
        cout<<endl<<endl;
*/

        int day=1,sum=0;   //这两个个参数要每一次都重置,否则结果不对。注意,vis在此重新定义的话好像不管用,OJ报“Wrong answer”.就拿到前面“memset(vis,0,sizeof(vis));”来初始化了
        for(int i=1;i<=n;i++)
        {
            if(day<=x[i].deadline)  //对应天数做对应期限的作业.在这里原本直接用的i来替代day的作用,但结果一直不对
            {
                day++;
                vis[i]=1;  //对已确定的作业做标记
            }
            else
            {
                int mix=x[i].reduce;
                int flag;
                for(j=1;j<=i-1;j++)   //查找这一天之前的罚分最少的作业
                {
                    if(vis[j]==1 && x[j].reduce<mix)
                    {
                        mix=x[j].reduce;
                        flag=j;
                    }
                }
                if(mix<x[i].reduce)  
             //前面罚分最小的作业比当前的作业小,则交换,找到了替死鬼
                {
					S xx=x[flag];
					x[flag]=x[i];
					x[i]=xx;
					i--;  //回退一个
                }
                else      
              //前面罚分最小的作业比当前的作业大,则当前作业甘愿被罚
                {
                    sum+=x[i].reduce;  //累计罚分
                }
            }
        }
        cout<<sum<<endl;
    }
}




 

题源:acm.hdu.edu.cn/showproblem…