2022/12/29总结

动态规划-01背包问题

立足于每一个物品,小偷都可以选择偷或者不偷,根据背包的容量,选择出最物尽其用的办法。

  1. 将上图的表格用一个二维数组存起来。

  1. 判断当前物品的重量是否小于背包当前遍历容量的大小,如果小于并且选择偷它以后的价值更高就选择偷这个物品,否则就不偷。

  1. 将每一种选取情况都写出来存入二维数组的模拟表格,最后这样偷到价值最高的物品就显而易见了。

#include"stdio.h"
int f[5][9]={0};
int w[5]={0,2,3,4,5};
int v[5]={0,3,4,5,8};
int max(int m,int n)
{
    if(n>m) return n;
    else return m;
 } 
main()
{
    int i,j;
    for(i=1;i<5;i++)
    for(j=1;j<9;j++)
    {
        if(w[i]>j)
        f[i][j]=f[i-1][j];
        else f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
    }
    for(i=0;i<5;i++)
    for(j=0;j<9;j++)
    printf("f[%d][%d]=%d\n",i,j,f[i][j]);    
}

考前的临时抱佛脚

题目描述
这次期末考试,kkksc03 需要考 44 科。因此要开始刷习题集,每科都有一个习题集,分别有 s_1,s_2,s_3,s_4 s1, s2, s3, s4 道题目,完成每道题目需要一些时间,可能不等(A_1,A_2,\ldots,A_{s_1} A1, A2,…, As1,B_1,B_2,\ldots,B_{s_2} B1, B2,…, Bs2,C_1,C_2,\ldots,C_{s_3} C1, C2,…, Cs3,D_1,D_2,\ldots,D_{s_4} D1, D2,…, Ds4)。
kkksc03 有一个能力,他的左右两个大脑可以同时计算 22 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。
由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。
输入格式
本题包含 55 行数据:第 11 行,为四个正整数 s_1,s_2,s_3,s_4 s1, s2, s3, s4。
第 22 行,为 A_1,A_2,\ldots,A_{s_1} A1, A2,…, As1 共 s_1 s1 个数,表示第一科习题集每道题目所消耗的时间。
第 33 行,为 B_1,B_2,\ldots,B_{s_2} B1, B2,…, Bs2 共 s_2 s2 个数。
第 44 行,为 C_1,C_2,\ldots,C_{s_3} C1, C2,…, Cs3 共 s_3 s3 个数。
第 55 行,为 D_1,D_2,\ldots,D_{s_4} D1, D2,…, Ds4 共 s_4 s4 个数,意思均同上。
输出格式
输出一行,为复习完毕最短时间。
输入输出样例
输入 #1复制
1 2 1 3 5 4 3 6 2 4 3
输出 #1复制
20
说明/提示
1\leq s_1,s_2,s_3,s_4\leq 201≤ s1, s2, s3, s4≤20。
1\leq A_1,A_2,\ldots,A_{s_1},B_1,B_2,\ldots,B_{s_2},C_1,C_2,\ldots,C_{s_3},D_1,D_2,\ldots,D_{s_4}\leq601≤ A1, A2,…, As1, B1, B2,…, Bs2, C1, C2,…, Cs3, D1, D2,…, Ds4≤60。
  1. 本题也是一个01背包问题。

  1. 因为这个同学的左右脑可以同时计算两道题目,所以用总共花的时间除以2,选择出较大的时间。

#include"stdio.h"
void sort(int a[],int n)
{
    int i,j,t;
    for(i=0;i<n;i++)
    for(j=1;j<n;j++)
    if(a[i]>a[j])
    {
        t=a[i];
        a[i]=a[j];
        a[j]=t;
    }
 } 
int max(int n,int m)
{
    if(n>m) return n;
    else return m;
}
main()
{
    int s[4],a[25],i,j,sum=0;
    int line,dp[30][2000];
    for(i=1;i<=4;i++)
    scanf("%d",&s[i]);
    for(i=1;i<=4;i++)
    {
        int v=0,num=0;
        for(j=1;j<=s[i];j++)
        {
        scanf("%d",&a[j]);
        v+=a[j];
        }
        sort(a,j);
        for(line=1;line<=s[i];line++)
        {
            for(j=1;j<=v/2;j++)
            {
                dp[line][j]=dp[line-1][j];
                if(j>=a[line]) 
                dp[line][j]=max(dp[line-1][j-a[line]]+a[line],dp[line][j]);
                num=max(dp[line][j],num);
            }
        }
        sum+=max(num,v-num);
    }
    printf("%d",sum);    
}

PERKET

题目描述
Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s s 和苦度 b b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。
输入格式
第一行一个整数 n n,表示可供选用的食材种类数。
接下来 n n 行,每行 22 个整数 s_i si 和 b_i bi,表示第 i i 种食材的酸度和苦度。
输出格式
一行一个整数,表示可能的总酸度和总苦度的最小绝对差。
输入输出样例
输入 #1复制
1 3 10
输出 #1复制
7
输入 #2复制
2 3 8 5 8
输出 #2复制
1
输入 #3复制
4 1 7 2 6 3 8 4 9
输出 #3复制
1
说明/提示
数据规模与约定
对于 100\%100% 的数据,有 1 \leq n \leq 101≤ n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1 \times 10^91×109,酸度和苦度不同时为 11 和 00。
  1. 该题我个人认为和上面的题目有点神似,都是立足于当选然后选择要或者不要,然后将每种情况都算出来。

  1. 使用了dfs算法。

  1. 在主函数调用fun函数时,注意酸度要计算的是乘积,所以初始值为1.

  1. 在进行递归调用时有两个分支就是在当前的酸度和苦度的情况下,是否要加下一种材料。

  1. 当递归到底进行判断时,要注意什么材料都没有的情况,这种情况就是苦度为0的时候,这是需要排除的。

#include"stdio.h"
#include"math.h"
long long a[20][2],min=999999,n;
void fun(int sd,int kd,int step)
{
    int i,t,x=0;
    if(step==n)
    {
        t=abs(sd-kd);
        if(min>t&&kd!=0) min=t;
        return;
    }
    step++;
    fun(sd*a[step][0],kd+a[step][1],step);
    fun(sd,kd,step);
}
main()
{
    int i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    scanf("%d %d",&a[i][0],&a[i][1]);  
    fun(1,0,0);    
    printf("%d",min);
}

小结

  1. 学习了01背包相关的知识。

  1. 01背包问题一般使用在每个物体数量只有一个,选择情况只有不选和选一个两种情况时。

  • 不放物品i:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以被背包内的价值依然和前面相同。)

  • 放物品i:由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值