Manchester


私信TA

用户名:wenyajie

访问量:332013

签 名:

在历史前进的逻辑中前进,这个逻辑就是人心向背的逻辑

等  级
排  名 1
经  验 65548
参赛次数 1
文章发表 188
年  龄 0
在职情况 学生
学  校 Xiamen University
专  业 计算机科学

  自我简介:

在历史前进的逻辑中前进,这个逻辑就是人心向背的逻辑

解题思路:

这个问题贪心算法是无法求出最优解的,因为可能还会剩下时间,但是一个剩下的时间又不够采药;

所以这个题的原型就是01背包,动态规划求最优解;

下面先解释第一张图:(可采药时间为10,五种药A  B  C  D  E )

2017-12-02 00-49-02屏幕截图.png

假设有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];
      }
   }

2017-12-02 00-45-47屏幕截图.png

把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 人评分

  评论区

好牛
2024-10-05 23:51:16
#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分
2024-03-02 15:30:00
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分,大神来看看
2023-12-17 14:11:11
各路大神,请帮忙看一下,哪里出问题了
#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);
 }
2022-01-18 12:06:07
神犇强的可拍!
2021-08-15 10:40:37
噗。这你只考虑了最简单的情况,只适用于前面几个药材刚好就是答案的情况,没考虑到每个药材的性价比问题,所以问题不小
2020-05-04 16:46:10
#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-03-31 21:01:15
优秀
2020-02-14 12:05:11