我在过去两天试图解决this问题。我没有得到正确的结果。 接受的解决方案是首先对链的数量进行排序。我不明白他们为什么这样做。 只是第一项任务是正确的。对于第二项任务,答案是错误的,第三次限制超过了。
这是我的代码:
#include<iostream>
using namespace std;
int main() {
int t;
cin>>t;
while(t--) {
long n=0;
int f=0,c=0,cuts=0;
cin>>n>>c;
int toJoint=c-1;
int A[c];
for (int i =0;i<c;i++)
cin>>A[i];
if (c>2){
for (int i =0;i<c;i++) {
if (A[i]==1) {
f++;
cuts++;
toJoint-=2;
if(toJoint<=1) break;
}
}
if (toJoint>0){
if (f==0) cout<<toJoint<<endl;
else cout<<(cuts+toJoint)<<endl;
}
else cout<<cuts<<endl;
}
else if (c==1) cout<<0<<endl;
else cout<<++cuts<<endl;
}
return 0;
}
答案 0 :(得分:1)
您有以下操作,每个操作都可用于将两个链链接在一起:
最优解决方案永远不需要使用(1),因此目标是确保尽可能多的操作是(3)s,其余的是(2)s。明显的最佳方法是从最小链条的末端反复切割甜甜圈,并用它将最大的两条链条粘在一起。这是对链进行分类的原因。即便如此,将长度放入堆中可能会更快,并且只需要尽可能多地提取最小元素。
现在问题:你的算法只对单个甜甜圈使用操作(3),但不会尝试通过从最小链的末端切割甜甜圈来制作更多单个甜甜圈。就像Jarod42指出的那样 反例,它不是最佳的。
我还应该指出你使用的是VLA
int A[c];
是非标准扩展名。要严格,您应该使用std::vector
代替。
为了完整性,这是一个例子:
std::sort(A.begin(), A.end());
int smallest_index = 0;
int cuts = 0;
while (M > 1)
{
int smallest = A[smallest_index];
if (smallest <= M - 2)
{
// Obliterate the smallest chain, using all its donuts to link other chains
smallest_index++;
M -= smallest + 1;
cuts += smallest;
}
else
{
// Cut M - 2 donuts from the smallest chain - linking the other chains into one.
// Now there are two chains, requiring one more cut to link
cuts += M - 1;
break;
}
}
return cuts;
(免责声明:仅针对样本数据进行测试,可能会在角落情况下失败或根本无法正常工作。)