Uva 147 Dollars (DP_简单)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&page=show_problem&problem=83


题目大意给定一个小数n,问11个数0.05,0.10,0.20.0.,50,1,2,5,10,20,50,100组合,相加之和为n的组合个数,和顺序无关。


解题思路:分11次转移,转移方程为:dp[i+num[k]] += dp[i](dp[i]为组合成i的不重复种数)。不能合在一起转移,这样会导致重复,破坏dp的无后效性。本题double输入相当蛋疼,就像万恶的几何一样,要考虑精度问题,299.90是一组很特殊的数据,化整的话很可能变成29989。答案会超32位int,要用long long,Uva的环境是GNU C++。

   本题还可以像背包那样做,复杂度一样。由于本题复杂度不高,没进行优化,不然可以对全部数除5,速度可以快上3-5倍。


测试数据:

0.20
300.00
299.90


代码:

#include <stdio.h>
#include <string.h>
#define MAX 81000
#define int64 long long


int64 dp[MAX];
int n,arr[20] = {5,10,20,50,100,200,500,1000,2000,5000,10000};


int main()
{
	int i,j,k;
	double tpn;


	while (scanf("%lf",&tpn),tpn > 0) {

		n = (tpn + 0.005) * 100;
		memset(dp,0,sizeof(dp));


		for (dp[0] = 1,i = 0; i <= 10; ++i) 
			for (j = 0; j <= n; ++j)
				dp[j+arr[i]] += dp[j];


		printf("%6.2lf%17lld\n",tpn,dp[n]);
	}

}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

你可能感兴趣的:(c,优化,测试)