uva 10313 Pay the Price

原题:
In ancient days there was a country whose people had very interesting habits. Some of them were lazy,some were very rich, some were very poor and some were miser. Obviously, some of the rich were miser(A poor was never miser as he had little to spend) and lazy but the poor were lazy as well (As the poor were lazy they remained poor forever). The following things were true for that country
a) As the rich were miser, no things price was more than 300 dollars (Yes! their currency was dollar).
b) As all people were lazy, the price of everything was integer (There were no cents and so beggars
always earned at least one dollar)
c) The values of the coins were from 1 to 300 dollars, so that the rich (who were idle) could pay any
price with a single coin.
Your job is to find out in how many ways one could pay a certain price using a limited number of
coins (Note that the number of coins paid is limited but not the value or source. I mean there was
infinite number of coins of all values). For example, by using three coins one can pay six dollars in 3
ways, 1+1+4, 1+2+3, and 2+2+2. Similarly, one can pay 6 dollars using 6 coins or less in 11 ways.
Input
The input file contains several lines of input. Each line of input may contain 1, 2 or 3 integers. The
first integer is always N (0 ≤ N ≤ 300), the dollar amount to be paid. All other integers are less than
1001 and non-negative.
Output
For each line of input you should output a single integer.
When there is only one integer N as input, you should output in how many ways N dollars can be
paid.
When there are two integers N and L1 as input, then you should output in how many ways N
dollars can be paid using L1 or less coins.
When there are three integers N, L1 and L2 as input, then you should output in how many ways
N dollars can be paid using L1,L1+1,…,L2 coins (summing all together). Remember that L1 is not
greater than L2.
Sample Input
6
6 3
6 2 5
6 1 6
Sample Output
11
7
9
11
大意:
從前有一個國家那裡的人民有非常有趣的習慣。有些人懶惰,有些人富有。有些人非常平窮,有些人小氣。明顯的有些有錢人小氣(貧窮人絕不會小氣,因為他本來就沒多少東西)並且懶惰,但是貧窮人也都懶惰(這也是他們永遠都貧窮的原因)。以下的事在這個國家都是真實的:

由於有錢人小氣,沒有任何東西的價格會超過300元。
由於貧窮人懶惰,每件東西的價格都是整數。(連乞丐要錢都至少要1元)
硬幣的面值從1到300元,所以那些懶惰的有錢人可以只用一個硬幣付任何的價錢。
你的任務是找出一個人要付一個價錢有多少種方法,條件是使用硬幣的數目是被限定的。例如:要用3個硬幣來付6元有3種方法:1+1+4、1+2+3、2+2+2。依此類推,一個人付6元最多使用6個硬幣的方法有11種。

Input

每組測試資料1列,每列可能含有1或2或3個整數。其中第一個整數一定是N(0 <= N <= 300),代表要付的錢是多少。其他的數均大於等於0,小於等於1000。

Output

對每組測試資料輸出一列,代表付N元有多少種方法,分為以下三種:

如果該組測試資料僅有1個整數,請輸出付N元的方法有多少種(用多少個硬幣不拘)。
如果該組測試資料有2個整數N、L1,請輸出付N元且最多用L1個硬幣的方法有多少種。
如果該組測試資料有3個整數N、L1、L2,請輸出付N元且最少用L1個硬幣,最多用L2個硬幣的方法有多少種。在這裡L1一定小於等於L2。
(以上来自lucky 猫)
注意数据:
input
0
0 0
0 1
0 0 0
0 0 1
0 1 1
0 1 2

output
1
1
1
1
1
0
0

#include <bits/stdc++.h>

using namespace std;
//fstream in,out;
string s;
long long dp2[1001][1001];
long long dp1[1001];
long long one(long long x)
{
    return dp1[x];
}
long long two(long long x,long long y)
{
    if(y<0)
        return 0;
    if(x==0)
        return 1;
    long long ans=0;
    for(int i=1;i<=y;i++)
        ans+=dp2[x][i];
    return ans;
}
long long three(long long x,long long y,long long z)
{
    return two(x,z)-two(x,y-1);
}
int main()
{
    ios::sync_with_stdio(false);
    memset(dp2,0,sizeof(dp2));
    dp2[0][0]=1;
    for(int i=1;i<=300;i++)
    {
        for(int j=i;j<=1000;j++)
        {
            for(int k=1;k<=1000;k++)
                dp2[j][k]+=dp2[j-i][k-1];
        }
    }
    memset(dp1,0,sizeof(dp1));
    dp1[0]=1;
    for(int i=1;i<=300;i++)
    {
        for(int j=i;j<=1000;j++)
            dp1[j]+=dp1[j-i];
    }
    stringstream ss;
    long long tmp1,tmp2,tmp3;
    while(getline(cin,s))
    {
        ss.clear();
        tmp1=tmp2=tmp3=-1;
        ss<<s;
        ss>>tmp1>>tmp2>>tmp3;
        if(tmp2==-1)
            cout<<one(tmp1)<<endl;
        else
        {
            if(tmp3==-1)
                cout<<two(tmp1,tmp2)<<endl;
            else
                cout<<three(tmp1,tmp2,tmp3)<<endl;
        }
    }
    return 0;
}

解答:
只输入一个数据的时候是一个经典的找零钱问题,就是告诉你有面额1到300的硬币,现在给你一个数,问你有多少种找钱方法。转移方程是dp[i]+=dp[i-coin[j]]。
当输入两个数据的时候,设置dp[j][k]表示找j元钱,使用的硬币数量是k个的找钱方法是多少。则转移方程为d[j][k]+=dp[j-coin[i]][k-1]。
当输入三个数据的时候,表是找钱的数目要大于等于l1小于等于l2,算出满足小于等于l1个硬币数目的值减去满足l2-1的值即可。 注意要用long long

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值