• HDU 2079 dp解法


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

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5115    Accepted Submission(s): 3944


    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个学分的组合数。
     
    Sample Input
    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
    Sample Output
    2
    445
     
    题意  中文题,不说了
    题解   这题我们设一个dp[ i ]数组( i 表示学分数,dp[i]就是组成i学分的组合数),枚举每个课程,求出包括前面课程所能组成的学分,对数组进行更新
    0.0......说的自己都不明白---_---!!!。
    AC代码
     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <iostream>
     6 #include <sstream>
     7 #include <algorithm>
     8 #include <string>
     9 #include <queue>
    10 #include <vector>
    11 #define maxn 100005
    12 #define maxm 50000
    13 using namespace std;
    14 typedef long long ll;
    15 int dp[50];
    16 struct  course
    17 {
    18   int s;
    19   int n;
    20 }f[10];
    21 int main(int argc, char const *argv[])
    22 {
    23   int t;
    24   cin>>t;
    25   while(t--)
    26   {
    27     int n,m;
    28     cin>>n>>m;
    29     memset(dp,0,sizeof(dp));
    30     for(int i=1;i<=m;i++)
    31     {
    32       cin>>f[i].s>>f[i].n;
    33     }
    34     dp[0]=1;
    35     for(int i=1;i<=m;i++)       //枚举课程
    36     {
    37       for(int j=n;j>=f[i].s;j--)      //枚举价值,要从大到小推!
    38       {
    39         for(int k=1;k<=f[i].n;k++)    ////枚举这个物品的个数,如果当前枚举到的价值能放入此物品的话,就加上之前的价值
    40         {
    41           if(j>=k*f[i].s)
    42             dp[j]+=dp[j-k*f[i].s];       //更新数组
    43           else
    44             break;
    45         }
    46       }
    47     }
    48     cout<<dp[n]<<endl;
    49   }
    50   return 0;
    51 }

    另一种 从小到大推,别人写的,摘自http://www.lai18.com/content/2463208.html

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <iostream>
     6 #include <sstream>
     7 #include <algorithm>
     8 #include <string>
     9 #include <queue>
    10 #include <vector>
    11 #define maxn 100005
    12 #define maxm 50000
    13 using namespace std;
    14 typedef long long ll;
    15 int main()
    16 {
    17   int T, n, num, a[10], b[10], c1[41], c2[41];
    18   //由于1<=num<=8,所以a,b开到10;由于1<=n<=40,所以c1,c2开到41
    19   scanf("%d", &T);
    20   while (T--) 
    21   {
    22     scanf("%d%d", &n, &num);
    23     for (int i = 1;i <= num;i++)
    24       scanf("%d%d", &a[i], &b[i]);
    25     memset(c1, 0, sizeof(c1));
    26     memset(c2, 0, sizeof(c2));
    27     c1[0] = 1;//由于本题对每个a[i]有个数限制,所以不能使数组c1初始化1【那样相当于默认学分为1的课程无限个】
    28     //但是可以在相乘多项式前多乘一个1,所以赋值c1[0] = 1,同时下面是从i=1开始的
    29     for (int i = 1;i <= num;i++) 
    30     {//i表示乘到了第几项
    31       for (int j = 0;j <= n;j++)
    32       {
    33         for (int k = 0;k + j <= n&&k <= b[i]*a[i];k += a[i])//a[i]是第i个多项式的单个课程学分
    34           c2[k + j] += c1[j];
    35       }
    36       memcpy(c1, c2, sizeof(c1));//c2赋给c1
    37       memset(c2, 0, sizeof(c2));//c2清零
    38     }
    39     printf("%d
    ", c1[n]);
    40   }
    41   return 0;
    42 }

    还可以用母函数写 可是我不会母函数 有时间去研究研究~

                                                                                                                                                                                                                                                                                                                                                                                                             
  • 相关阅读:
    动词 + to do、动词 + doing
    图像直线检测——霍夫线变换
    x=min(x, y)
    x=min(x, y)
    算法 Tricks(三)—— 数组(序列)任意区间最小(大)值
    算法 Tricks(三)—— 数组(序列)任意区间最小(大)值
    分治法求解切割篱笆
    分治法求解切割篱笆
    GMM的EM算法实现
    秒杀多线程第二篇 多线程第一次亲热接触 CreateThread与_beginthreadex本质差别
  • 原文地址:https://www.cnblogs.com/stranger-/p/7307866.html
Copyright © 2020-2023  润新知