【发布时间】:2015-05-17 15:23:26
【问题描述】:
我正在尝试解决 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
我尝试使用动态编程(自上而下的方法)来解决这个问题。但我无法得到正确的答案。递归函数可能有问题。这是我的代码:
#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;
}
上述方法有什么问题?
【问题讨论】:
-
首先,您通常不应该包含
<bits/*>头文件,尤其是<bits/stdc++.h,除非您确实需要该文件包含的所有头文件。 仅包含您需要的头文件,在您的情况下为<cstdio>和<iostream>。在 C++ 程序中使用scanf有什么原因吗? -
@JoachimPileborg 我知道在 C++ 代码中使用
或 scanf 不是一个好方法。但是这些策略被用于编程竞赛。这是我的编程竞赛问题代码。 -
别人有坏习惯,不代表你就应该有。如果您想成为一名优秀的程序员,请从一开始就使用良好的编程技术和良好的习惯。并且不要参加编程竞赛,它们不会真正让你成为一名优秀的程序员,除非你认为混淆和未注释的代码很好。学习好的编程技术、基本和高级的数据结构和算法,最重要的是如何编写好的、可读的和可维护的代码,然后如果你还想参加这些竞赛。
-
我认为你不应该在这里使用 dp,对于像 10000 1 2 3 这样的东西,你的方法可能需要几个小时来计算。
-
如果你把它分解为“5 5 3 2”的输入,你在某个时刻得到 val = 1,在你完成 n = 5, n = 0 ( 1 + dp (0) ), val = 1。然后当您执行 5 - 2 - 2 时,您还剩 1 个,然后您的所有测试 if(n >= a[i]) 失败,您返回 val,即 1,然后您将 1 添加到 1,当你有 5 - 2 - 2 并且你做 val = 1 + dp(1),到目前为止你有 2,然后你把那个 2 添加到另一个 1,当你做 val = 1 + dp( 3),所以你总共得到 3。对于“7 5 5 2”的输入,你从 7 中减去 2 3 次,最后你得到 1,它仍然算数。
标签: c++ algorithm dynamic-programming