甜甜圈链 - codechef

时间:2015-09-16 14:49:16

标签: c++

我在过去两天试图解决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;
} 

1 个答案:

答案 0 :(得分:1)

您有以下操作,每个操作都可用于将两个链链接在一起:

  1. 在中间切割一条链(&gt; = 3)(减去0条链)
  2. 在末端切割一条链(> = 2)(链条少一条)
  3. 切一个甜甜圈(少了2个链子)
  4. 最优解决方案永远不需要使用(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;
    

    免责声明:仅针对样本数据进行测试,可能会在角落情况下失败或根本无法正常工作。)