如何使用动态编程自上而下方法解决此问题?

时间:2015-05-17 15:23:27

标签: c++ algorithm dynamic-programming

我试图通过Codeforces解决问题(http://codeforces.com/problemset/problem/189/A) 这是问题陈述:

  

Polycarpus有一条带子,长度为n。他希望以满足以下两个条件的方式切割色带:

     

切割后,每个带状件应具有长度a,b或c。   切割后,带状件的数量应最大。   帮助Polycarpus并找到所需的带状件数量   切割

     

输入   第一行包含四个空格分隔的整数n,a,b和c(1≤n,a,b,c≤4000) - 相应地,原始色带的长度和切割后的带状件的可接受长度。数字a,b和c可以重合。

     

输出   打印单个数字 - 最大可能的色带片数。保证至少存在一个正确的色带切割。

     

示例输入

     

5 5 3 2

     

示例输出

     

2

我尝试使用动态编程(Topdown方法)解决此问题。但我无法得到正确的答案。递归函数可能有问题。这是我的代码:

#include<bits/stdc++.h>
using namespace std;

int n,s;
int a[3];
int val,m=-1;
int dp(int n)
{
    if(n==0)
        return 0;
    for(int i=0;i<3;i++)
    {
        if(n>=a[i])
        {
            val=1+dp(n-a[i]);
        }
    }
    if(val>m)
        m=val;
    return m;
}

int main()
{
    scanf("%d %d %d %d",&n,&a[0],&a[1],&a[2]);
    cout<<dp(n)<<endl;
    return 0;
}

上述方法有什么问题?

4 个答案:

答案 0 :(得分:4)

有几个问题:

搜索错误

在你的行中

for(int i=0;i<3;i++)
{
    if(n>=a[i])
    {
        val=1+dp(n-a[i]);
    }
}
if(val>m)
    m=val;

您应该检查为val的不同选项获得的不同i的最大值。

错误终止

如果长度不为0并且没有可以切割色带,则应返回负无穷大等。您当前返回的m最初为-1(稍后会详细介绍)。这是错误的,对于长条带,基本上确保您只选择a,b和c的最小值。

使用Globals

一些全局变量,例如m被初始化一次,但是被递归修改。这不是“仅仅”坏的编程习惯 - 它没有做你想要的。

不再使用

通过无条件地调用递归,而不是重复使用以前的调用,您的运行时间不必要地高。

答案 1 :(得分:0)

int main() {
 int n, a, b, c;
 scanf("%d %d %d %d", &n, &cuts[0], &cuts[1], &cuts[2]);
 sort(cuts, cuts + 3);
 for (int i = 0; i <= n; i++) {
    max_cuts[i] = INT_MIN;
 }

 max_cuts[0] = 0;
 max_cuts[cuts[0]] = 1;
 max_cuts[cuts[1]] = 1;
 max_cuts[cuts[2]] = 1;

 for (int i = 1; i <= n; i++) {
    for (int j = 0; j < 3; j++) {
        if (cuts[j] > i) break;
        max_cuts[i] = max(max_cuts[i - cuts[j]] + 1, max_cuts[i]);
    }
 }
 printf("%d\n", max_cuts[n]);
 return 0;
}

答案 2 :(得分:0)

答案 3 :(得分:0)

您可以通过自上而下的方法解决此问题。dp问题始终检查所有可能的情况,然后为我们提供最佳解决方案。因此这是代码

#include<bits/stdc++.h>
using namespace std;
int a,b,c;
int DP[4001];
int solve(int n){
if(n == 0)return 0;
if(n<0) return INT_MIN;
if(DP[n] != -1)return DP[n];
else{
   DP[n] = max(1+solve(n-a),max(1+solve(n-b),1+solve(n-c)));
return DP[n];
}
}
int main(){
int n,x;
cin>>n>>a>>b>>c;
for(int i = 0;i<4001;++i){
DP[i] = -1;
}
x = solve(n);
cout<<x;
}