解题思路:
这个问题贪心算法是无法求出最优解的,因为可能还会剩下时间,但是一个剩下的时间又不够采药;
所以这个题的原型就是01背包,动态规划求最优解;
下面先解释第一张图:(可采药时间为10,五种药A B C D E )
假设有A,B,C,D,E,五种药,对应图中第三列,从(1)A开始,(1)代表第一种药A(这里为了好看上了编号);
m/t : m就是药的编号(比如你输入了三种药)他们的编号就对应1,2,3 编号0表示没有药; t为分配给你采药的时间分别从0到10,你会问t不是10吗,不是,你可以先这样理解,动态规划,就是把你有的时间从0开始,(这里时间为10),分成11中情况即:0到10,让你用;
再看第一列time[m]:表示采第m种药所要的时间;
再看第二列value[m]:表示第m种药的价值;
这两列就是你输入的M种药,对应的采药时间和价值;
看懂上面的后,最后来看m/t所对应的红色和蓝色的部分:这一部分我们用一个二维数组定义:sumvalue[m][t];这个的作用是用来存最大价值;你会问为什么用二维数组,先别急;这个问题不好解释;
接着看图m==0,代表着(0)no 那一行;t==0,对应着0下面的那一列;m==0这一行,和t==0这一列,对应的sumvalue[m][t]都为0,因为m==0,代表没药可采,价值肯定为0;t==0,可用来采药的时间为0,那价值也一定为0;所以在一定药把sumvalue[m][t]初始化为0;
明白了表的含义后,我么你就要知道表中sumvalue[m][t](即蓝色部分,红色部分上面解释了:初始化)是怎么来的:用就是这个公式:sumvalue[ m ] [ t ]=max { sumvalue[ m-1 ] [ t-time[m] ] + value[ m ] ,sumvalue[ m-1 ] [ t ] }
公式中红色字体中,有个隐含条件:[ t-time[m] ]要大于等于0;应为t的时间用来采time[m]的时间的药,要够,否则采不了,采不了的话sumvalue[ m ] [ t ]这个格子的值就等于sumvalue[ m-1 ] [ t ]格子的值; 能采的话,就是它俩取最大值;
最后sumvalue[ 5] [ 10]=15就是最优解;
以上是方法;
到这里你必须要会填表中sumvalue[ m] [ t ]部分(多天几遍后,你就找到规律了),否则下面的理论会感觉很空洞;
按照0 1背包,每一种药 m,有两种选择,1.采 2.不采 ,如果采的话那么价值sumvalue[ m] [ t ]=sumvalue[ m-1 ] [t-time[m] ] + value[ m ] (即 价值等于第m-1种药装入容量为t-time[m] 的时间中的价值加上第m个物品的价值value[ m ])这句话只有用背包才说的清楚; 如果不采的话sumvalue[ m ] [ t ]=sumvalue[ m-1 ] [ t ] 即第m种药不采的话,所得价值应该和前面采了前面m-1种药且剩余时间为t的价值相等; 这两种情况取最大值就是最优解;
sumvalue[ m ] [ t ]=max { sumvalue[ m-1 ] [ t-time[m] ] + value[ m ] ,sumvalue[ m-1 ] [ t ] } ;
实现过程:
void kaicai(int *value,int *time,int M,int T) { int m,t; for(m=1;m<=M;m++) { for(t=1;t<=T;t++) { if(time[m]<=t) sumvalue[m][t]=max(sumvalue[m-1][t-time[m]]+value[m],sumvalue[m-1][t]); else sumvalue[m][t]=sumvalue[m-1][t]; } }
把sumvalue[ m ] [ t ]打印出来就是这样;
注意事项:
建议去看看01背包,采药太抽象,总的来说,把那个表填出来,再看看多看看;
这是用一维数组解决的:不解释了,太难,把实现部分背得,以后直接用吧。
void kaicai(int *value,int *time,int M,int T) { int m,t; for(m=0;m<M;m++) { for(t=T;t>=time[m];t--) { if(sumvalue[t-time[m]]+value[m]>sumvalue[t]) sumvalue[t]=sumvalue[t-time[m]]+value[m]; } } printf("%d\n",sumvalue[T]); }
#include<stdio.h> void caiyao(); void kaicai(int *value,int *time,int M,int T); int sumvalue[1000]; /*--------------------------------------------------------------*/ int main() { caiyao(); return 0; } /*--------------------------------------------------------------*/ void caiyao() { int T,M; int value[100],time[100]; while(scanf("%d%d",&T,&M)!=EOF) { for(int i=0;i<M;i++) scanf("%d%d",&time[i],&value[i]); kaicai(value,time,M,T); } return ; } /*--------------------------------------------------------------*/ void kaicai(int *value,int *time,int M,int T) { int m,t; for(m=0;m<M;m++) { for(t=T;t>=time[m];t--) { if(sumvalue[t-time[m]]+value[m]>sumvalue[t]) sumvalue[t]=sumvalue[t-time[m]]+value[m]; } } printf("%d\n",sumvalue[T]); }
参考代码:
#include<stdio.h> void caiyao(); void kaicai(int *value,int *time,int M,int T); int sumvalue[102][1001]; #define max(x,y) (x)>(y)?(x):(y) /*--------------------------------------------------------------*/ int main() { caiyao(); return 0; } /*--------------------------------------------------------------*/ void caiyao() { int T,M; int value[100],time[100]; while(scanf("%d%d",&T,&M)!=EOF) { for(int i=1;i<=M;i++) scanf("%d%d",&time[i],&value[i]); kaicai(value,time,M,T); } return ; } /*--------------------------------------------------------------*/ void kaicai(int *value,int *time,int M,int T) { int m,t; for(m=1;m<=M;m++) { for(t=1;t<=T;t++) { if(time[m]<=t) sumvalue[m][t]=max(sumvalue[m-1][t-time[m]]+value[m],sumvalue[m-1][t]); else sumvalue[m][t]=sumvalue[m-1][t]; } } /*for(int i=1;i<=M;i++) for(int j=1;j<=T;j++) { printf("%d ",sumvalue[i][j]); if(j%T==0) printf("\n"); }*/ printf("%d\n",sumvalue[M][T]); }
0.0分
38 人评分
#include<stdio.h> #include<string.h> #include<math.h> int MAX(int c[],int M){ int k=0,max=c[0]; for(int j=0;j<M;j++) { if(c[j]>max) { max = c[j]; k = j; } } return k; } int fun(int T,int M){ int n,m,sum=0,max,k=0,P; int b[M],c[M]; P = M; for(int i=0;i<M;i++) { scanf("%d%d",&n,&m); b[i] = n; c[i] = m; // printf("%d %d\n",b[i],c[i]); } // printf("===========\n"); while(P>0&&T>0) { k=MAX(c,M); // printf("%d\n",k); if(T>=b[k]){ 只有18分
int main() { int i, j, k = 0; /*总采药时间*/ int a; /*山洞里草药数目*/ int b; /*山洞里采时间和价值*/ double c[1000], d[1000]; double e[1000]; scanf("%d %d",&a, &b); for (i = 0; i < b; i++) { scanf("%lf %lf", &c[i], &d[i]); } for (i = 0; i < b; i++) { e[i] = d[i] / c[i]; } for (i = 0; i < b - 1; i++) { for (j = 0; j < b - i - 1; j++) { if (e[j] > e[j + 1]) { int tmp = e[j]; e[j] = e[j + 1]; e[j + 1] = tmp; } } } int f = 0; for (i = b - 1; i > -1; i--) { f += c[i]; if (f < a) { k += d[i]; } f = f - c[i]; } printf("%d", k); return 0; } 只有9分,大神来看看
ccc 2023-12-17 14:11:45 |
e是性价比
各路大神,请帮忙看一下,哪里出问题了 #include<stdio.h> int f(int T,int n,int*t,int *v) { int i,j,MAX=0; if(n<=0||T<=0) MAX=0; else { MAX=f(T,n-1,t,v); if(t[n]<=T) { MAX=f(T-t[n],n-1,t,v)+v[n]>MAX?f(T-t[n],(n-1),t,v)+v[n]:MAX; } } return MAX; } int main() { int T,n,i,j,V=0,MAX=0; scanf("%d%d",&T,&n); int t[n+1],v[n+1]; for(i=1;i<=n;i++) scanf("%d%d",&t[i],&v[i]); MAX=f(T,n,t,v); printf("%d",MAX); }
#include<stdio.h> int main() { int i,j,x,y; int a,sum=0; int T,M; scanf("%d%d",&T,&M); for(i=0;i<M;i++) { scanf("%d%d",&x,&y); if(T>=x) {sum+=y; T-=x;} } printf("%d\n",sum); } 这实现了求出价值 很简单 但是 有弊端 而且很多 哪位大神能指导下吗 谢谢
啊噗啊噗 2020-05-15 12:39:49 |
你这是按顺序拿东西,不看价值,能拿就拿