这是来自Codechef的问题,但请耐心等待。 https://www.codechef.com/ZCOPRAC/problems/ZCO12004
比赛是为了准备在印度举行的区域计算奥林匹克运动会,所以它不是一场竞争性的比赛,我可以从中获得这样的比赛。只需要一些帮助就可以看出我的代码有什么问题,因为我有一种感觉,我忽略了一些大而愚蠢的东西。 :P
问题基本上表明:
想象一下,有一个向量或数组,使得最后一个元素是 与第一个相关联。找到添加的最低总和 每个相邻元素对中的至少一个。 (请参阅链接) 因此,通过添加1 + 1 + 2,{1,2,1,2,2}输出的答案将是4。
这是我的解决方案:
它的作用基本上是它向后迭代,从向量的末尾到开头,并存储从向量M中可以实现的最低可能总和,在向量M中。基本上使用动态编程完成。 / p>
M的前两个元素是可能的答案。然后我做一些检查,看看哪些是可能的。如果M [1]小于M [0],那么数组/向量的最后一个元素应该包含在M [1]中计算的总和中。
#include <algorithm>
#include <iostream>
#include <vector>
#define print(arr) for(auto pos = arr.begin(); pos != arr.end(); ++pos) cout << *pos << " "; cout << endl;
typedef long long int ll;
using namespace std;
int main() {
int N;
ll x;
cin >> N;
vector <ll> A;
vector <ll> M(N+2);
fill(M.begin(),M.end(),0);
for (int i = 0; i < N; i++) {
cin >> x;
A.push_back(x);
}
for (int i = N-1; i >= 0; i--) {
M[i] = A[i]+*min_element(M.begin()+i+1, M.begin()+i+3);
}
if (M[0] <= M[1]) cout << M[0] << endl;
else if (M[1] < M[0]) {
if (M[N-1] <= (M[N-2])) cout << M[1] << endl;
else cout << M[0] << endl;
}
}
但是,我无法在子任务2中传递2个测试用例。我认为我的代码的最后一部分是不正确的。知道我可能做错了吗?要不然,或者我误解了这个问题。术语“相邻对”有点含糊不清。因此,如果有4个数字3,4,5,6相邻对是否意味着相邻对是{(3,4)(4,5)(5,6)(6,3)}或{或者(3,4) )和(5,6)或(4,5)和(6,3)}?我的代码考虑前者。
非常感谢@User_Targaryen清除了对这个问题的疑虑!基本上我的实现和你的一样,因为我使用动态编程背后的想法是一样的。只有在这种情况下我的M(你的dp)与你的相反。无论如何我得到了AC! :)(我留下了一些愚蠢的调试声明,并且想知道15分钟出了什么问题xD)更新的解决方案:
#include <algorithm>
#include <iostream>
#include <vector>
#define print(arr) for(auto pos = arr.begin(); pos != arr.end(); ++pos) cout << *pos << " "; cout << endl;
typedef long long int ll;
using namespace std;
int main() {
int N;
ll x, sum = 0;
cin >> N;
vector <ll> A;
vector <ll> M(N+2);
fill(M.begin(),M.end(),0);
for (int i = 0; i < N; i++) {
cin >> x;
A.push_back(x);
}
for (int i = N-1; i >= 0; i--) {
M[i] = A[i]+*min_element(M.begin()+i+1, M.begin()+i+3);
}
//print(M);
reverse(A.begin(), A.end());
vector <ll> M2(N+2);
fill(M2.begin(),M2.end(),0);
for (int i = N-1; i >= 0; i--) {
M2[i] = A[i]+*min_element(M2.begin()+i+1, M2.begin()+i+3);
}
//print(M2);
cout << min(M[0], M2[0]) << endl;
}
答案 0 :(得分:2)
我在这里附上我接受的解决方案:
#include<iostream>
using namespace std;
int main()
{
int i,j,k,n;
cin>>n;
int a[n],dp1[n],dp2[n];
int ans;
for(i=0;i<n;i++)
{
cin>>a[i];
dp1[i]=0;
dp2[i]=0;
}
if(n <= 2)
cout<< min(a[0],a[1]);
else{
i = 2;
dp1[0] = a[0];
dp1[1] = a[1];
while (i < n){
dp1[i] = a[i] + min(dp1[i-1],dp1[i-2]);
i = i + 1;
}
dp2[0] = a[n-1];
dp2[1] = a[n-2];
i = n-3;
j = 2;
while(i >= 0){
dp2[j] = a[i] + min(dp2[j-1],dp2[j-2]);
i = i - 1;
j = j + 1;
}
ans = min(dp1[n-1], dp2[n-1]);
cout<<ans;
}
return 0;
}
dp1[i]
表示迄今为止最合适的解决方案是在解决方案中包含i-th
元素
dp2[i]
表示迄今为止最合适的解决方案是在解决方案中包含i-th
元素
dp1[]
从左到右计算,而dp2[]
从右到左计算
minimum
和dp1[n-1]
的{{1}}是最终答案。
我完成了你的作业!
编辑: @Alex :动态编程是一项非常难以教授的内容。这是某种做法自然而然的事情。让我们考虑一下我的解决方案(暂时忘掉你的解决方案):
dp2[n-1]
意味着我在解决方案中明确包含了最后一个元素,并且满足任何2个相邻元素中的至少一个需要选择的约束,因为它始终如下:
dp1[n-1]
dp1[i] = a[i] + min(dp1[i-1],dp1[i-2]);
意味着我在解决方案中明确包含了第一个元素,并且也满足了任何2个相邻元素中至少有一个需要选择的约束。
所以,上述两个中的最小值将给出最终结果。
答案 1 :(得分:1)
M[i]
数组中的想法是“解决方案的最低成本,假设其中包含索引i
”。
条件if (M[0] <= M[1])
表示“如果包含索引0优于不包括它,则完成”。
如果这种情况不成立,那么,首先,支票if (M[1] < M[0])
是多余的 - 将其删除。它不会修复任何错误,但至少会减少混淆。
如果条件为false,则应输出M[1]
,但前提是它与有效解决方案相对应。也就是说,由于未选择索引0,因此应选择最后一个索引。但是,使用您的数据结构,无法知道M [1]是否对应于选择最后一个索引的解决方案 - 此信息将丢失。
要解决此问题,请考虑构建两个数组 - 例如数组L
,其含义为“解决方案的最低成本,假设其中包含索引i
,以及索引N-1
包含在其中 ”
然后,在您的计划结束时,输出最小值M[0]
和L[1]
。