zoukankan      html  css  js  c++  java
  • POJ3181——DP(找钱3)——Dollar Dayz

    Description

    Farmer John goes to Dollar Days at The Cow Store and discovers an unlimited number of tools on sale. During his first visit, the tools are selling variously for $1, $2, and $3. Farmer John has exactly $5 to spend. He can buy 5 tools at $1 each or 1 tool at $3 and an additional 1 tool at $2. Of course, there are other combinations for a total of 5 different ways FJ can spend all his money on tools. Here they are: 

            1 @ US$3 + 1 @ US$2 
    1 @ US$3 + 2 @ US$1
    1 @ US$2 + 3 @ US$1
    2 @ US$2 + 1 @ US$1
    5 @ US$1
    Write a program than will compute the number of ways FJ can spend N dollars (1 <= N <= 1000) at The Cow Store for tools on sale with a cost of $1..$K (1 <= K <= 100).

    Input

    A single line with two space-separated integers: N and K.

    Output

    A single line with a single integer that is the number of unique ways FJ can spend his money.

    Sample Input

    5 3

    Sample Output

    5
    大意:仍然是找钱问题,不过用原来的方法发现数用unsigned long long 都存不下。。只能看成完全背包来做,分成两块
    以下来自ACM荣耀大神 传送门

    整数划分是把一个正整数 N 拆分成一组数相加并且等于 N 的问题.
    比如:
    6
    5 + 1 (序列)
    4 + 2, 4 + 1 + 1
    3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
    2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
    1 + 1 + 1 + 1 + 1 + 1

    假设F(N,M) 整数 N 的划分个数,其中 M 表示将 N 拆分后的序列中最大数

    考虑边界状态:
    M = 1 或者 N = 1 只有一个划分 既: F(1,1) = 1
    M = N : 等于把M - 1 的划分数加 1 既: F(N,N) = F(N,N-1) + 1 
    M > N: 按理说,N 划分后的序列中最大数是不会超过 N 的,所以 F(N,M ) = F(N,N)
    M < N: 这个是最常见的, 他应该是序列中最大数为 M-1 的划分和 N-M 的划分之和, 比如F(6,4),上面例子第三行, 他应该等于对整数 3 的划分, 然后加上 2 的划分(6-4) 所以 F(N,M) = F(N, M-1) + F(N-M,M)

    用动态规划来表示

     dp[n][m]= dp[n][m-1]+ dp[n-m][m]
               
               dp[n][m]表示整数 n 的划分中,每个数不大于 m 的划分数。
               则划分数可以分为两种情况:
     
               a. 划分中每个数都小于 m, 相当于每个数不大于 m- 1, 故
                  划分数为 dp[n][m-1].
     
               b. 划分中有一个数为 m. 那就在 n中减去 m , 剩下的就相当
                  于把 n-m 进行划分, 故划分数为 dp[n-m][m];

    
    
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long  a[1005][105],b[1005][105];
    long long inf = 1e18;
    int main()
    {
        int n,m,i,j,k;
        while(~scanf("%d%d",&n,&m)){
            memset(a,0,sizeof(a));
            memset(b,0,sizeof(b));
            for(int i = 0 ; i <= m ; i++)
                a[0][i] = 1;
            for(int j = 1; j <= m ; j++){
                for(int i= 1; i <= n; i++){
                    if(i < j){
                        a[i][j] = a[i][j-1];
                        b[i][j] = b[i][j-1];
                      continue;
                    }
                    b[i][j] = b[i][j-1] + b[i-j][j] + (a[i][j-1] + a[i-j][j])/inf;
                    a[i][j] = (a[i][j-1] + a[i-j][j])%inf;
                }
            }
            if(b[n][m])
                printf("%lld",b[n][m]);
            printf("%lld
    ",a[n][m]);
        }
    return 0;
    }
    View Code
    
    
    
     
  • 相关阅读:
    调用Type.InvokeMember()时出现MissingMethodException
    C#学习之Delegate
    WCF之元数据交换 (Metadata Exchange)
    定义Enum的开始和结束,这样就能循环Enum了
    定制自己的Visual Studio的Debugger Visualizer
    C#中 #if DEBUG 和 Conditional("DEBUG")的区别
    从哪里开始学习Windows 8?(zz)
    Macro 小总结
    WPF应用的图标
    如何把 Visutal studio中的“printonbreakpoint”消息打印在程序的任何地方
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4466758.html
Copyright © 2011-2022 走看看