codeforces(排序加动态规划)

链接:https://ac.nowcoder.com/acm/problem/21314
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

牛牛正在打一场CF
比赛时间为T分钟,有N道题,可以在比赛时间内的任意时间提交代码
第i道题的分数为maxPoints[i],题目的分数随着比赛的进行,每分钟减少pointsPerMinute[i]
这是一场比较dark的Cf,分数可能减成负数
已知第i道题需要花费 requiredTime[i] 的时间解决
请问最多可以得到多少分
 

输入描述:

第一行输入两个整数N,T (1 ≤ N ≤ 50, 1 ≤ T ≤ 100000)
第二行输入n个整数maxPoints[i]
第三行输入n个整数pointsPerMinute[i]
第四行输入n个整数requiredTime[i]
1 ≤ maxPoints[i],pointsPerMinute[i],requiredTime[i] ≤ 100000

输出描述:

输出一个整数

示例1

输入

复制

1 74
502
2
47

输出

复制

408

示例2

输入

复制

2 40000
100000 100000
1 100000
50000 30000

输出

复制

0

示例3

输入

复制

3 75
250 500 1000
2 4 8
25 25 25

输出

复制

1200

示例4

输入

复制

3 30
100 100 100000
1 1 100
15 15 30

输出

复制

97000

备注:

子任务1: n <= 10
子任务2: n <= 20
子任务3: 无限制

如果直接从第一个到第n的最优解就是01背包的做法。但是这题 后面的分数会被前面的影响,所以这里需要性价比进行排序

 

假设有两个相邻的a,b信息。选择第一个先做的总分为a.mx-a.re*a.po+ b1=b.mx-(a.re+b.re)*b.po;

选择第二个先做的总分为 b.mx-a.re*b.po+b2=a.mx-(a.re+b.re)*a.po;  所以 性价比的排序方式就是a.mx-a.re*a.po+ b1=b.mx-(a.re+b.re)*b.po>b.mx-a.re*b.po+b2=a.mx-(a.re+b.re)*a.po;

 

排序后套一个 01背包就可以了

AC代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define in(x) scanf("%d",&x)
#define ind(x) scanf("%lld",&x)
#define out(x) printf("%d ",x);
#define outln(x) printf("%lld\n",x);
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
#define PE(x,y) x=((x)+(y))%mod
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; 
for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const int N=50,M=1e5;
ll dp[N+10][M+10]; 

struct node
{
	ll mx,po;
	ll re;
}a[N+10];
bool cmp(node a,node b){
	ll a1=a.re*a.po;
	ll b1=(a.re+b.re)*b.po;
	
	ll a2=b.re*b.po;
	ll b2=(a.re+b.re)*a.po;
	return a1+b1<a2+b2;
}
int main()
{
	int n,t;
	in(n);in(t);
	rep(i,1,n) ind(a[i].mx);
	rep(i,1,n) ind(a[i].po);
	rep(i,1,n) ind(a[i].re);
	sort(a+1,a+1+n,cmp);
//	rep(i,1,n){
//		printf("%lld %lld %d\n",a[i].mx,a[i].po,a[i].re);
//	}
	rep(i,1,n){
		per(j,t,0){
			if(j-a[i].re>=0) 
			dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].re]+(a[i].mx-a[i].po*j));
			dp[i][j]=max(dp[i][j],dp[i-1][j]);
			//printf("dp:%lld j:%d %lld %lld\n",dp[i][j],j,dp[i-1][j-a[i].re],(a[i].mx-a[i].po*j));
		}
	}
	ll ans=0;
	rep(j,0,t) ans=max(ans,dp[n][j]);
	cout<<ans<<endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙大学ccsu_deer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值