您的位置:首页 > 其它

uva10313(二维多重DP)

2016-05-18 15:55 309 查看
题目大意:

给出N,l1,l2,N表示钱的面值,问将N拆分可以有多少种拆分数。

有三种情况:

1,给出N,将N拆分成面值不超过N的硬币可以有多少种不同的拆分数。

2,给出N和l1,将N拆分成面值不超过l1的硬币可以有多少种不同的拆分数。

3,给出N和l1和l2,将N拆分成面值在l1到l2范围内的硬币可以有多少种不同的拆分数。

思路:

dp[i][j]表示将面值为i拆分成面值不超过j的硬币可以有多少种拆分。

dp[i][j] += dp[i - j][j] + dp[i][j - 1]。

这是选与不选面值为j的硬币的问题。

dp[i -j][j]表示选择面值为j的硬币,dp[i][j - 1]表示不选择面值为j的硬币。

注意输入!!

强大的sscanf返回的是被赋值的个数。

代码:

#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
const int maxn = 310;
long long dp[maxn][maxn];
char str[310];
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++) {
//      for(int k = 0; k <= 300; k++) {
if(j - 1 >= 0)
dp[i][j] +=  dp[i][j - 1];
if(i - j >= 0)
dp[i][j] += dp[i - j][j];
//  }
}
}
}
void solve() {
int N,l1,l2;
int  n = sscanf(str,"%d%d%d",&N,&l1,&l2);
l1 = l1 > 300?300:l1;
l2 = l2 > 300?300:l2;
if(n > 2) {
printf("%lld\n",dp
[l2] - dp
[l1 - 1]);
}
else if(n > 1) {
printf("%lld\n",dp
[l1]);
}
else
printf("%lld\n",dp

);
}

int main() {
init();
while(gets(str) != NULL) {
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: