您的位置:首页 > 其它

uva 10313 - Pay the Price

2014-08-06 20:52 369 查看
Problem B
Pay the Price
Input: standard input
Output: standard output
Time Limit: 2 seconds
Memory Limit: 32 MB
 

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+41+2+3and 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 12 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 NL1 and L2 as input, then you should output in how many ways N dollars can be paid using L1L1+1 …, L2coins
(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

这道题其实关键是利用Ferrers 图像转换出问题的本质来,这里有一个结论:

(a) 整数n拆分成k个数的和的拆分数,和数n拆分成最大数为k的拆分数相等。

自然有推论:(b)
整数n拆分成最多不超过m个数的和的拆分数,和n拆分成最大不超过m的拆分数相等。

详见:点击打开链接

剩下的应该不成问题了,就是之前做了好多的硬币拆分问题,典型的完全背包。

代码:

#include<cstdio>
#include<iostream>
using namespace std;

long long dp[310];
int main()
{
int n,a,b;
char s[100];
while(~scanf("%d",&n)){
gets(s);
a=b=-1;
sscanf(s,"%d%d",&a,&b);
for(int i=1;i<=n;i++) dp[i]=0;
dp[0]=1;
if(a==-1&&b==-1){
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
dp[j]+=dp[j-i];
}
else if(b==-1){
for(int i=1;i<=a;i++)
for(int j=i;j<=n;j++)
dp[j]+=dp[j-i];
}
else{
for(int i=1;i<=a-1;i++)
for(int j=i;j<=n;j++)
dp[j]+=dp[j-i];
long long tmp=dp
;
for(int i=max(a,1);i<=b;i++)
for(int j=i;j<=n;j++)
dp[j]+=dp[j-i];
dp
-=tmp;
}
if(b!=-1&&a>0) dp[0]=0;
else dp[0]=1;
printf("%lld\n",dp
);

}
return 0;
}


这道题WA了无数次,一直没有发现代码错误。网上找了好多程序,其实或多或少都有错!

那到底错在什么地方呢?首先这道题目n可以为0,这个时候到底要输出什么答案呢?其实dp[0]值初始化为1,纯属是为了递推。0根本是无法分解,因此答案是0.

不,这题也不能这么想,这题给出的是分解个数范围,0是无法分解,因此可以说成0可以分解成0个数,因此0或者0 a或者0 0 b,这些形式的dp[0]=1,其他情况dp[0]=0;

这道题告诉我做题切不可大意啊!测试数据弱了些,网上有很多代码在0这块处理地并不是很完美的都能过。

其实这题目n=0没有意义,[b]分解成0个数这种说法也不确切,不然的话无法分解成功也能算一种了,分解成0个数只是不能分解的一种特例,这样的话1也可以看成1(本身)+分解成的0个数。[/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: