您的位置:首页 > 其它

UVA - 10313 Pay the Price 整数的划分问题 01背包

2014-11-19 20:09 316 查看
题目大意:给出一个价值N的货品,有300种货币,价值分别为1-300,可能会给出L1和L2,当给出的只有N的时候,要求你求出用N个货币表示价值为N的货品有几种方法,当给出的只有N和L1的时候,要求你给出用1到L1个货币表示价值为N的商品有多少种表示方法,当给出N,L1,L2时,要求你给出用L1到L2个货币能表示价值为N的货品有多少种方法

解题思路:解法1.看Staginner大神的,如果不理解的话,请看点击打开链接,用dp[i][j]表示价值为i的用面值最大为j的货币表示有多少种方法,假设不用j这个货币,则dp[i][j]
= dp[i][j-1],如果用了j这个货币,则dp[i][j] = dp[i-j][j],所以dp[i][j] = dp[i-j][j] + dp[i][j-1]

解法2:用dp[i][j]表示用j个货币能组成价值为i的商品有多少种组合方法,则dp[i][j] = dp[i][j] + dp[i-k][j-1] ,这就相当于01背包问题了,初始化dp[0][0] = 1

解法1代码

#include<cstdio>
#include<cstring>
#define maxn 305
int N,L1,L2,count;
char str[100];
long long dp[maxn][maxn];

void init() {
	memset(dp,0,sizeof(dp));
	dp[0][0] = 1;

	for(int i = 0 ; i <= 300; i++) 
		for(int j = 1; j <= 300; j++){
			if(i - j >= 0)
				dp[i][j] +=  dp[i-j][j];
			if(j - 1 >= 0)
				dp[i][j] += dp[i][j-1];
		}
}

int main() {

	init();
	while(gets(str)) {
		int flag = sscanf(str,"%d%d%d",&N,&L1,&L2);
		L1 = L1 > 300 ? 300:L1;
		L2 = L2 > 300 ? 300:L2;
		if(flag == 1)
			printf("%lld\n",dp

);
		else if(flag == 2)
			printf("%lld\n",dp
[L1]);
		else if(flag == 3 && L1 == 0)
			printf("%lld\n",dp
[L2]);
		else if(flag == 3 && L1 > 0)
			printf("%lld\n",dp
[L2] - dp
[L1-1]);
	}
	return 0;
}


解法2代码:
#include<cstdio>
#include<cstring>
#define maxn 305
long long dp[maxn][maxn];
char str[100];
int N,L1,L2;
void init() {
	int n = 300;
	memset(dp,0,sizeof(dp));
	dp[0][0] = 1;
	for(int i = 1; i <= n; i++)
		for(int j = i; j <= n; j++)
			for(int k = 1; k <= n; k++)
				dp[j][k] += dp[j-i][k-1];
}

int main(){
	init();
	while(gets(str)) {	
		int flag = sscanf(str,"%d%d%d",&N,&L1,&L2);
		L1 = L1 > 300 ? 300:L1;
		L2 = L2 > 300 ? 300:L2;
		long long sum = 0;
		if(flag == 1)
			for(int i = 0; i <= N; i++)
				sum += dp
[i];
		else if(flag == 2)
			for(int i = 0 ; i <= L1; i++)
				sum += dp
[i];
		else if(flag == 3)
			for(int i = L1; i <= L2; i++)
				sum += dp
[i];
		printf("%lld\n",sum);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: