ZOJ 3703 Happy Programming Contest(贪心+0/1背包)

81 篇文章 1 订阅
27 篇文章 0 订阅

首先要对每个问题按照所用时间排序,才能保证出来的惩罚时间最小

用一个dp数组保存在j时间解决问题i所能得到的attractiveness最大值

用一个solcnt数组保存解决的问题数量

用一个preTime数组保存当前问题的提交时间

用一个peanlSum保存在j时间解决问题i所用的惩罚时间总和

这样就可以DP了

比赛的时候用的一维数组怎么都过不了,赛后用了二维数组才过了

#include <iostream>
#include <memory.h>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=1010;
struct prob
{
	int attr,sl;
	bool operator<(const prob &rhs)const{
		return sl<rhs.sl||(sl==rhs.sl&&attr>rhs.attr);
	}
}pbs[65];
int dp[65][maxn],solcnt[65][maxn],penalSum[65][maxn],preTime[65][maxn],len,n;
int main(){
	int t;
	scanf("%d",&t);
	while (t--){
		scanf("%d%d",&len,&n);
		for (int i=1;i<=n;++i){
			scanf("%d",&pbs[i].sl);
		}
		for (int i=1;i<=n;++i){
			scanf("%d",&pbs[i].attr);
		}
		sort(pbs+1,pbs+n+1);
		memset(dp,0,sizeof(dp));
		memset(solcnt,0,sizeof(solcnt));
		memset(preTime,0,sizeof(preTime));
		memset(penalSum,0,sizeof(penalSum));
		for (int i=1;i<=n;++i){
			for (int j=0;j<=len;++j){
				if(pbs[i].sl<=j){
					int u1=dp[i-1][j],u2=dp[i-1][j-pbs[i].sl]+pbs[i].attr;
					int v1=solcnt[i-1][j],v2=solcnt[i-1][j-pbs[i].sl]+1;
					int q1=penalSum[i-1][j],q2=penalSum[i-1][j-pbs[i].sl]+preTime[i-1][j-pbs[i].sl]+pbs[i].sl;
					if(u1<u2||(u1==u2&&v1<v2)||(u1==u2&&v1==v2&&q2<q1)){
						dp[i][j]=u2;
						solcnt[i][j]=v2;
						penalSum[i][j]=q2;
						preTime[i][j]=preTime[i-1][j-pbs[i].sl]+pbs[i].sl;;
					}else{
						dp[i][j]=u1;
						solcnt[i][j]=v1;
						penalSum[i][j]=q1;
						preTime[i][j]=preTime[i-1][j];
					}
				}else{
					dp[i][j]=dp[i-1][j];
					solcnt[i][j]=solcnt[i-1][j];
					penalSum[i][j]=penalSum[i-1][j];
					preTime[i][j]=preTime[i-1][j];
				}
				
			}
		}
		printf("%d %d %d\n",dp[n][len],solcnt[n][len],penalSum[n][len]);
	}
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值