zoukankan      html  css  js  c++  java
  • 又见背包。hdu 2079

    选课时间(题目已修改,注意读题)

    Problem Description
    又到了选课的时间了,xhd看着选课表发呆,为了想让下一学期好过点,他想知道学n个学分共有多少组合。你来帮帮他吧。(xhd认为一样学分的课没区别)
     
    Input
    输入数据的第一行是一个数据T,表示有T组数据。
    每组数据的第一行是两个整数n(1 <= n <= 40),k(1 <= k <= 8)。
    接着有k行,每行有两个整数a(1 <= a <= 8),b(1 <= b <= 10),表示学分为a的课有b门
    Output
    对于每组输入数据,输出一个整数,表示学n个学分的组合数。
    2
    2 2
    1 2
    2 1
    40 8
    1 1
    2 2
    3 2
    4 2
    5 8
    6 9
    7 6
    8 8
     
    2
    445
    思路:   dp[i][j]=dp[i-1][j]+dp[i-t][j-a[i]*t];
    代表   前i中课获得j个学分的种类数 =  第i种课程没有获得 + 第i种课程获得了学分,并且个数t个。
    个数的装入需要一些技巧,为了防止对第i种课程的重复使用,要合理的投放。 分组背包的思想。(其实也不能这么说,关键是要自己画图,就能得到了)
    对于n->a[i]  向n投放 1个或2个或3个...t个的第j种课程。
     
    代码:
    #include<stdio.h>
    int main()
    {
        int f[41],a[9],b[9];
        int i,j,k,n,m,t;
        while(scanf("%d",&n)>0)
        {
            while(n--)
            {
                scanf("%d%d",&m,&k);
                for(i=1;i<=k;i++)
                    scanf("%d%d",&a[i],&b[i]);
                for(i=1;i<=m;i++)
                    f[i]=0;
                f[0]=1;
                for(i=1;i<=k;i++)
                  for(j=m;j>=a[i];j--)
                    for(t=1;t<=b[i]&&j>=a[i]*t;t++)  //关键。
                    if(f[j-a[i]*t]!=0)
                      f[j]=f[j]+f[j-a[i]*t];
            printf("%d\n",f[m]);
            }
        }
        return 0;
    }
  • 相关阅读:
    Springboot打jar 包
    mysql 函数
    SFTP的使用
    Java Swing
    消息中间件之ActiveMQ
    对象的四种引用关系
    vs的url传参
    后台管理两级类别
    $.dialog弹层---lhgDialog
    正则小数验证和去除中间空格
  • 原文地址:https://www.cnblogs.com/tom987690183/p/3021213.html
Copyright © 2011-2022 走看看