欢迎光临
我们一直在努力

一道简单的背包问题

一道简单的背包问题 P10955

大致题意:给定一个数,求可以拆分成至少两个正整数数的和的总数(数字可以无限用)

问题分析:很明显是dp,仔细思考,由于数字可以无限使用,并且目标总和不变,那么,这大概是一个完全背包了

我们令,f[j]为求数字i的方案总数,考虑转移方程,f[j] = f[j] + f[j – i]

为什么是这样的呢?

假设我们处理完了数字1 ~ i- 1,现在要加入i,那么对于任意总和j,j的方案数可以用i,也可以不用,

如果用i,那么剩下的就是 j – i,如果不用,那么还是旧的j ,二者相加,就得到了上述方程

#include <iostream>
#include <algorithm>

using namespace std;

#define int long long
const int N = 4e3 + 10;
const int M = 2147483648;

int n;

int f[N];

signed main()
{
cin>>n;
f[0] = 1;
for(int i= 1;i <=n ;i ++)
{
for(int j = 1;j <= i; j ++)
f[i] = (f[i] + f[i j]) % M;
}
f[n] ;

cout<<f[n]<<endl;

return 0;
}

以上为一维的做法,那么二维的该如何做呢?

二维那就更容易了,设

f

[

i

]

[

j

]

f[i][j]

f[i][j]为用前i种数字求j的总数,

显然,转移方程如下 :

f

[

i

]

[

j

]

=

f

[

i

1

]

[

j

]

+

f

[

i

]

[

j

i

]

f[i][j] = f[i – 1][j] + f[i][j – i]

f[i][j]=f[i1][j]+f[i][ji] (j >= i),

f

[

i

]

[

j

]

=

f

[

i

1

]

[

j

]

f[i][j] = f[i -1][j]

f[i][j]=f[i1][j] (j < i)

代码不再赘述

赞(0)
未经允许不得转载:171主机测评 » 一道简单的背包问题
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址