[HDU] 1789 Doing Homework again

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1789

方法:

既然一个作业超期了,不管超期多久都只扣一次固定的学分。又因为每个作业只要一天,所以可以看出n个作业n天就可以做完,那些截至日期大于n天的就不用考虑了。只考虑截至日期在n天内的。可以这样考虑,设截至日期在n天内的作业如果全部按时完成的话得到的学分的和是sum,再设一个实际获得学分t_sum(初始0),然后一个作业按时完成 t_sum就加上学分,超期的就不管,然后把原来的问题转变为在截至日期在n天内的作业中安排一个顺序使得获得的学分之和t_sum最大,然后用sum-t_sum得到扣除的最少学分,这样得到原来问题的解。

设D[i]为一个截至日期,D[i].values截至日期是D[i]的作业有哪些,然后从第一天开始计算,计算第D[i]前必须做完的作业中选择D[i]个作业来做能获得的最大学分,计算过程为,首先计算截止期是第一天的作业,从D[1].values选择出最高学分那个,当然只选1个,然后把它并入D[2].values,再选出2个最高学分的作业,然后再将这两个并入D[3].values,再选出3个最高分的哪个。。。。最后在D[n].values中选择最高分的n个作业,将学分相加得到t_sum。

问题解决了。

代码:

#include <iostream>
#include <queue>
using namespace std;
int n;
struct Course
{
    int deadLine;
	int get;
};
struct DeadLine
{
	priority_queue<int> values;
};
Course courses[1001];
DeadLine deadlines[1001];
int main()
{
    int tc=0;
    scanf("%d",&tc);
    while(tc>0)
    {
        scanf("%d",&n);
        int sum = 0;
        for(int i =1;i<=n;i++)
            scanf("%d",&courses[i].deadLine);
        for(int i =1;i<=n;i++)
            scanf("%d",&courses[i].get);
		priority_queue<int> no_values ;
		for(int i =1;i<=1000;i++)
			deadlines[courses[i].deadLine].values = no_values;
		for(int i =1;i<=n;i++)
		{
			if(courses[i].deadLine<=n)
			{
				sum+=courses[i].get;
				deadlines[courses[i].deadLine].values.push(courses[i].get);
			}
		}
		int re =0;
		for(int i=1;i<=n;i++)
		{
			int t_re = 0;
			priority_queue<int> t_values = deadlines[i].values;
			if(!deadlines[i].values.empty())
			{
				int j=0;
				while(j<i && !deadlines[i].values.empty())
				{
					t_re+=deadlines[i].values.top();
					deadlines[i].values.pop();
					j++;
				}
			}
			re = re>t_re ?re :t_re;
			bool foundOne =false;
			int k=i;
			while(k<n)
			{
				if(!deadlines[k+1].values.empty())
				{
					foundOne =true;
					break;
				}
				k++;
			}
			if(foundOne)
			{
		  
				int j=0;
				deadlines[i].values = t_values;
				while(j<i && !deadlines[i].values.empty())
				{
					deadlines[k+1].values.push(deadlines[i].values.top());
					deadlines[i].values.pop();
					j++;
				}
				i=k;
				
			}
		}
		cout<<sum-re<<endl;
        tc--;
    }
    return 0;
}

 感想:模拟,注意代码中基于概率优化的部分

原文地址:https://www.cnblogs.com/kbyd/p/3238608.html