甜甜圈连锁店- codechef

Chain of doughnut - codechef

本文关键字:codechef 连锁店 甜甜圈      更新时间:2023-10-16

这两天我一直在努力解决这个问题。我没有得到正确的结果。被接受的解决方案是先对链的数量进行排序。我不明白他们为什么这么做。只有第一个任务是正确的。第二题答错,第三题超过时限。

下面是我的代码:
#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. 中间剪一条链(>=3)(少剪0条链)
  2. 在最后剪一条链(>=2)(少1条链)
  3. 切一个甜甜圈(少2个)

最优解永远不需要使用(1),因此目标是确保尽可能多的操作是(3)s,其余的是(2)s。显然,最好的方法是从最小的链条的末端反复切一个甜甜圈,然后用它把最大的两条链条粘在一起。这就是对链进行排序的原因。即便如此,将长度放入堆中可能会更快,并且只提取最小元素的次数是我们需要的。

现在回答问题:你的算法只在单个甜甜圈上使用操作(3),但没有试图通过从最小链的末端切割甜甜圈来制造更多的单个甜甜圈。正如Jarod42指出的那样反例,它不是最优的。


我还应该指出你对VLAs的使用

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;

(免责声明:仅在样本数据上测试,可能在角落情况下失败或根本不工作。)