題目描述
題目分析
- 對於T=2,顯然我們可以設一個DP:f[i]表示第一天買賣前你有i元,第二天買賣後最多可以有多少錢。
- 狀態轉移也是比較顯然的:f[i]=max(i,f[i−a[k][1]]+a[k][2])
- 其中k表示的是紀念品的編號,a[k][1]與a[k][2]分別表示該物品第1天和第2天的價值。
- 最後的答案輸出f[m]就可以了,時間複雜度是O(1000n)的。
- 那如果T>2呢。
- 也有一個小結論:存在一種最優方案,使得第i天買入的紀念品在i+1天全部賣出,重新買入。
- 證明:假設最優方案中,有一個商品,必須在第i天買,第i+k(k>1)天賣出。顯然這種方法不比“在第i天買,第i+1天賣出,再在第i+1天買,第i+2天賣出......在第i+k−1天買,最終在第i+k天賣出”更優。
- 依據這個結論,我們可以把剛纔的T=2的方法循環重複做T−1次,時間複雜度O(1000Tn)。
代碼
#include<cstdio>
#include<cstring>
using namespace std;
const int N=110,M=1e4+100;
int a[N][N],f[N][M];
int mymax(int x,int y) {return x>y?x:y;}
int main()
{
freopen("souvenir.in","r",stdin);
freopen("souvenir.out","w",stdout);
int t,n,m;
scanf("%d%d%d",&t,&n,&m);
for(int i=1;i<=t;i++)
for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
memset(f,0,sizeof(f));
int maxn=10000;
for(int i=0;i<=maxn;i++) f[1][i]=i;
for(int i=t;i>=2;i--){
for(int j=0;j<=maxn;j++) f[i][j]=j;
for(int j=1;j<=n;j++){
if(a[i-1][j]>=a[i][j]) continue;
for(int k=a[i-1][j];k<=maxn;k++){
int t=f[i][k-a[i-1][j]]+a[i][j];
f[i][k]=mymax(f[i][k],t);
}
}
for(int j=maxn;j>=0;j--){
if(f[i][j]<=maxn) {maxn=j;break;}
}
}
for(int i=2;i<=t;i++) m=f[i][m];
printf("%d\n",m);
return 0;
}