大致题意
有(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),有显然的转移:
总钱数达到(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