题目背景
直达通天路·小A历险记第三篇
题目描述
在猴王的帮助下,小A终于走出了这篇荒山,却发现一条波涛汹涌的河拦在了自己的面前。河面上并没有船,但好在小A有n个潜水工具。由于他还要背重重的背包,所以他只能背m重的工具,又因为他的力气并不是无限的,河却很宽,所以他只能背有v阻力的工具。但是这条河下有非常重要的数据,所以他希望能够停留的时间最久。于是他找到了你,让你告诉他方案。
输入输出格式
输入格式:
三个数m,v,n如题目所说
接下来n行,每行三个数ai,bi,ci分别表示所含的重力,阻力,能够支撑的时间
输出格式:
第一行一个数,表示最长的时间
接下来一行,若干个数,表示所选的物品
输入输出样例
输入样例#1:
100 100 3 50 60 289 40 10 116 50 50 106
输出样例#1:
405 1 2
说明
1<=m,v<=200,n<=100
数据保证一定有方案。
若有多种方案,输出前面尽量小的方案。
/* 第一问很容易,重点在求方案 自己想了一个方法,设一个c[i][j]表示更新f[i][j]的最后一个元素,在更新f时顺便更新c, 求方案时不停往前找,感觉应该对,但错了一个点,调了很长时间发现,我想找的c[x][y], 它的真正的f值,可能比我想要的大,此时就出现了错误。正解是用一个类似于链的东西ans, 将两个有联系的c连了起来。 */ #include<cstdio> #include<iostream> #define M 210 #define N 110 using namespace std; int f[M][M],ans[N][M][M],c[M][M],w1[N],w2[N],v[M],m1,m2,n; int read() { char c=getchar();int num=0,flag=1; while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();} while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();} return num*flag; } void print(int now,int a,int b) { if(now<=0)return; print(ans[now][a][b],a-w1[now],b-w2[now]); printf("%d ",now); } int main() { m1=read();m2=read();n=read(); for(int i=1;i<=n;i++) w1[i]=read(),w2[i]=read(),v[i]=read(); for(int i=1;i<=n;i++) for(int j=m1;j>=w1[i];j--) for(int k=m2;k>=w2[i];k--) if(f[j-w1[i]][k-w2[i]]+v[i]>f[j][k]) { f[j][k]=f[j-w1[i]][k-w2[i]]+v[i]; c[j][k]=i; ans[i][j][k]=c[j-w1[i]][k-w2[i]]; } printf("%d ",f[m1][m2]); print(c[m1][m2],m1,m2); return 0; }