• 周二. 8月 16th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

P3891 [GDOI2014]采集资源

admin

11月 28, 2021

大致题意

(m)块钱,(n)种苦工,每个苦工都有一个购入值(a_i)和每秒收入(b_i),求让总钱数达到(t)的最少时间

(n≤100,m,t≤1000, a_i,b_i≤2^{31})

分析

考虑到每秒钟的决策和花费金钱数及当前每秒收入量有关,且这里的每秒收入量数值较大,不妨设(f(i,j))表示在前(i)秒总钱数为(j)时的每秒收入量

设该秒花费的钱数为(k),花(k)元钱能买到的最大收入量为(v_k),有显然的转移:

$f(i,j) = max(f(i-1,j+k-f(i-1,j+k)-v_k)+v_k)$

总钱数达到(t)时输出(i)即可

小坑点:初始钱数大于t时直接输出0

//xcxc82 2021/7/30
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1010;
inline int read(){
	int X=0; bool flag=1; char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
	if(flag) return X;return ~(X-1);
}
int n,m,t;
int a[MAXN],b[MAXN];
int f[MAXN][MAXN],g[MAXN];
int main(){
	n = read(),m = read(),t = read();
	if(m>=t){
		cout<<0<<endl;
		return 0;
	}
	for(int i=1;i<=n;i++){
		a[i] =read(),b[i] = read();
	}
	memset(f,-1,sizeof(f));
	memset(g,-1,sizeof(g));
	g[0] = 0,f[0][m] = 0;
	for(int i=0;i<=n;i++){
		for(int j=a[i];j<=1000;j++){
			g[j] = max(g[j],g[j-a[i]]+b[i]);
		}
	}
	for(int i=0;i<=1000;i++){
		for(int j=0;j<=t;j++){
			if(f[i][j]!=-1)
			for(int k=0;k<=j;k++){
				f[i+1][j-k+g[k]+f[i][j]] = max(g[k]+f[i][j],f[i+1][j-k+g[k]+f[i][j]]);
				if(j-k+g[k]+f[i][j]>=t){
					cout<<i+1;
					return 0;
				}
			}
		}
	}
}

重构于2021/7/30

发表回复

您的电子邮箱地址不会被公开。