2021-11-02

完全背包详解

  1. 大家应该都知道完全背包这一种题型,是dp的一种类型,其实dp说白了就是“一直优秀”,就是把所走的每一步都当做最优的,然后在这个基础上让他更加优秀。

  2. 上例子:
    题目描述
    LiYuxiang 是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同种类的草药,采每一种都需要一些时间,每一种也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
    如果你是 LiYuxiang,你能完成这个任务吗?
    此题和原题的不同点:
    每种草药可以无限制地疯狂采摘。
    药的种类眼花缭乱,采药时间好长好长啊!师傅等得菊花都谢了!

  3. 题解:和01背包相比其实就是多了无限制采药。

    1. 01背包再加一个k循环(取每种的个数)
    2. 二维数组获取 f[i][j]=max(f[i][j],f[i][j-w[i]+v[i])
      解:其实就是拿现在的和之前已经推出的最优比。
    3. 一维数组获取 f[j]=max(f[j],f[j-w[i]]+v[i])
      解:同理二维
  4. 我们来看一下一维的每层(每层在这里指每个种类)循环后的dp数组的值
    代码:

    for(int i=1;i<=n;i++)
    	for(int j=w[i];j<=m;j++){
    		dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    		for(int z=0;z<=j;z++){
    			printf("%d ",dp[z]);		
    		} 
    		printf("\n");
    		printf("%d\n",j);
    		printf("\n");
    	}
    

在这里插入图片描述

	如图,我们着重看一下,种类变化后的输出(这个是由第二个(5,2)变为第三个(18,6))
	第二重循环中为什么j从w[i]开始呢,因为,有w[i]才能装下,之前都装不下,是其他情况中的最优。
	进入下一个种类时,f[j]=max(f[j],f[j-w[i]]+v[i]),f[j]是从前几个种类得到的最优,f[j-w[i]]+v[i]是返回到只选择了(j-w[i])的时间时的最优。
	比如我现在t=18 目前的最优是10 而现在选择的是(18,11)
	设此时f[j]=f[18]=10
	则f[j-w[i]]+v[i]=f[18-18]+11=f[0]+11=11  f[0]是之前所算出最优时的值。

补:i和j的含义特别重要,其中i是第几个种类,用于得到v[i],w[i],j则是已用的时间,用于得到dp数组。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者消费者问题是一个经典的同步问题,其中生产者和消费者共享一个缓冲区,生产者向缓冲区中生产产品,消费者从缓冲区中消费产品。在多线程的环境下,生产者和消费者可能会同时访问缓冲区,因此需要对缓冲区进行同步控制。 以下是一个简单的生产者消费者问题的实现: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int count = 0; int in = 0; int out = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t empty = PTHREAD_COND_INITIALIZER; pthread_cond_t full = PTHREAD_COND_INITIALIZER; void *producer(void *arg) { int i; for (i = 0; i < 20; i++) { pthread_mutex_lock(&mutex); while (count == BUFFER_SIZE) { pthread_cond_wait(&empty, &mutex); } buffer[in] = i; in = (in + 1) % BUFFER_SIZE; count++; printf("producer: produced %d\n", i); pthread_cond_signal(&full); pthread_mutex_unlock(&mutex); } pthread_exit(NULL); } void *consumer(void *arg) { int i, data; for (i = 0; i < 20; i++) { pthread_mutex_lock(&mutex); while (count == 0) { pthread_cond_wait(&full, &mutex); } data = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; printf("consumer: consumed %d\n", data); pthread_cond_signal(&empty); pthread_mutex_unlock(&mutex); } pthread_exit(NULL); } int main() { pthread_t tid1, tid2; pthread_create(&tid1, NULL, producer, NULL); pthread_create(&tid2, NULL, consumer, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0; } ``` 在代码中,我们定义了一个大小为10的缓冲区,使用一个计数器count来记录缓冲区中产品的数量,in和out分别表示生产者和消费者在缓冲区中的位置。我们使用了两个条件变量empty和full来控制生产者消费者的同步。 在生产者中,当缓冲区已满时,生产者会等待empty条件变量,直到缓冲区有空位。当生产者生产完一个产品后,会唤醒消费者,并释放互斥锁。 在消费者中,当缓冲区为空时,消费者会等待full条件变量,直到缓冲区有产品。当消费者消费完一个产品后,会唤醒生产者,并释放互斥锁。 通过使用互斥锁和条件变量,我们可以保证生产者和消费者的正确同步,避免了竞争条件和死锁等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值