子集和问题(应用--换零钱)POJ2229:Sumsets

我一直在纠结换零钱这一类型的题目,今天好好絮叨一下,可以说他是背包的应用,也可以说他是单纯的dp。暂且称他为dp吧。

先上一道模板题目。

sdut2777: 小P的故事——神奇的换零钱

题目描述

已知A国经济很落后,他们只有1、2、3元三种面值的硬币,有一天小P要去A国旅行,想换一些零钱,小P很想知道将钱N兑换成硬币有很多种兑法,但是可惜的是他的数学竟然是体育老师教的,所以他不会啊、、、他只好求助于你,你可以帮他解决吗?

提示:输入数据大于32000组。

输入

 每行只有一个正整数N,N小于32768。

输出

 对应每个输入,输出兑换方法数。

示例输入

100 
1500

示例输出

884 
188251

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <math.h>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,dp[32800],w[4];
int main()
{
    w[1]=1;
    w[2]=2;
    w[3]=3;
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    for(int i=1; i<=3; i++)//依次添加每类货币
    {
        for(int j=i; j<=32768; j++)//枚举可使用第i类货币每一种可能的数和
        {
            dp[j]=dp[j]+dp[j-w[i]];// (累计前i-1类货币构成j-w[i]的方式数)
//dp[j]=dp[j]+dp[j-w[i]]的含义为:使用前i类货币时的货币组成可能可能的数(dp[j])=当使用前i-1类货币时的货币组成可能的数(dp[j])
//+选择使用一个i类货币+剩余钱数(j-w[i])组成的货币的数目(前i类)---这里有点背包的感觉,所以说他是背包的应用
} } while(scanf("%d",&n)!=EOF) { printf("%d\n",dp[n]); } return 0; }

 

POJ2229:

Description

Farmer John commanded his cows to search for different sets of numbers that sum to a given number. The cows use only numbers that are an integer power of 2. Here are the possible sets of numbers that sum to 7: 

1) 1+1+1+1+1+1+1 
2) 1+1+1+1+1+2 
3) 1+1+1+2+2 
4) 1+1+1+4 
5) 1+2+2+2 
6) 1+2+4 

Help FJ count all possible representations for a given integer N (1 <= N <= 1,000,000). 

Input

A single line with a single integer, N.

Output

The number of ways to represent N as the indicated sum. Due to the potential huge size of this number, print only last 9 digits (in base 10 representation).

Sample Input

7

Sample Output

6
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <math.h>
#define inf 0x3f3f3f3f
typedef long long ll;
#define mod 1000000000
using namespace std;
int n,w[10010],tt,zan,l,dp[1000010];
int main()
{
   tt=0;
   w[tt++]=1;
   for(int i=1;i<=1000;i++)
   {
       zan=pow(2,i);
       if(zan>1000000) break;
       w[tt++]=zan;
   }
   while(scanf("%d",&n)!=EOF)
   {
       memset(dp,0,sizeof(dp));
       dp[0]=1;
       for(int i=0;i<tt;i++)
       {
           if(dp[i]>n) break;
           for(int j=w[i];j<=n;j++)
           {
               dp[j]=(dp[j]+dp[j-w[i]])%mod;
           }
       }
       printf("%d\n",dp[n]);
   }
    return 0;
}

 

posted @ 2015-03-23 20:42  人艰不拆_zmc  阅读(306)  评论(0编辑  收藏  举报