http://acm.hdu.edu.cn/showproblem.php?pid=1789
有 N 份 homework ,每份有 deadLine 和 score,如果超过deadLine 还没做完,该homework的 score 将被扣去,做完每份homework的时间是相等的,为一天。求扣分最少的策略的扣分数。
解法一:动态规划
与 毕业bg 这题有诸多类似之处,代码也与之雷同,但不同的是,这道题中的 homework 的cost 是1,从而能用贪心优化(如果是>1的即使它们都相等也不能用贪心优化)
#pragma warning (disable:4786)
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 1000
int dp[MAX+10];
struct homeWork{
int deadLine;
int score;
};
homeWork ho[MAX+10];
int cmp( homeWork h1, homeWork h2 ){
return h1.deadLine < h2.deadLine;
}
int main(){
int t,n,i,j,sum;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
sum=0;
for( i = 0; i < n; i ++ )
scanf("%d",&ho[i].deadLine);
for( i = 0; i < n; i ++ ){
scanf("%d",&ho[i].score);
sum += ho[i].score;
}
//按 deadLine 升序排列
sort( ho, ho + n, cmp );
//dp数组中每一项设置为n个homework的score和
for( i = 0; i <= ho[n-1].deadLine; i ++)
dp[i] = sum;
for( i = 0; i < n; i ++){
for( j = ho[i].deadLine; j >= 1; j -- ){
if( dp[j-1] - ho[i].score < dp[j] )
dp[j] = dp[j-1] - ho[i].score;
}
}
int min = sum;
for( i = 1; i <= ho[n-1].deadLine; i ++){
if( dp[i] < min )
min = dp[i];
}
printf("%d\n",min);
}
}
解法二:贪心;将 homework 按 score 降序排列,同时用一个 size 为总天数的数组 time[ ] 记录每一天被使用的情况。对 homework 数组由前向后扫描,若 该homework的 deadLine 这天已被使用,则向前扫描 time 直到扫描到未被使用的一天,若扫描到头都没有符合条件的,则这一homework只能被放弃,扣去它的score。
解法三:贪心;将 homework 按 deadLine 升序排列,由后往前扫描 天数 数组,每一天的安排如下贪心:选择deadLine不在这一天之前的还没被安排的最大 score 的homework ,将这一 homework 在这天完成。