UESTC Journey

In Tomb-sweeping Festival, Yangsir and her friends planned to have a journey in a park. The park has N attractions which form a circle and only between adjacent attractions there is a road, so there are N roads in total. On the way to the park, Yangsir and her friends lost their way. After several twists and turns, they arrived at the park but they still didn't know which attraction they are on now.



Looking at the park's map, Yangsir wanted to know that: if they set attraction X as starting point, what is the minimum time they needed to pass all N attractions at least once? They don't need to go back to the starting attraction and the time spend on attractions are ignored.

We number the N attractions from 1 to N clockwise, and the ith road is the road between ith and (i+1)th attraction, except that the Nth road is the road between N and 1. The N roads are all undirected.

Input

There are multiple test cases. The first line of the input will be an integer T (T <= 10) indicating the number of test cases.

For each test case, the first line is only one integer N (3 <= N <= 1000), representing the number of attractions in the park. In the second line there are N positive integers separated by one space representing the time needed to pass through the ith road. All the integers above are within 1,000,000.

Output

For each test case, print "Case #t: " first, in which t is the number of the test case starting from 1. Then output N integers separated by one space which are the minimum time needed if they start from 1st attraction, 2nd attraction,..., Nth attraction.

Sample Input

1
5
4 6 5 3 7

Sample Output

Case #1: 18 19 19 20 18 

分析:由于要把 N 个点都访问一遍,因而最优解必然要经过 N-1 条(种)边,且每
条(种)边至少经过一次。最优解也最多经过 N-1 条(种)边,因为经过 N-1 条
(种)边时,已经把 N 个点都访问至少一遍。因而可以枚举哪条边不走,之后
终点必然是这条边的两个端点之一。 假如起点到两个端点的距离分别是 S1, S2,
则 这 种 方 案 的 最 优 解 是 S1+S2+min(S1,S2). 以 这 个 起 点 的 最 优 解 是
min{S1+S2+min(S1,S2)}.总的复杂度为 N^2。 

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;
typedef long long LL;
const int N=1010;
int main()
{
    int t,n,a[N*2];
    LL sum,ans;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        scanf("%d",&n);
        sum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            a[i+n]=a[i];
            sum+=a[i];
        }
        a[0]=a[n];
        a[n*2+1]=a[1];

        printf("Case #%d:",ca);
        for(int i=1;i<=n;i++)
        {
            ans=sum-a[i]<sum-a[i-1]?sum-a[i]:sum-a[i-1];
            LL temp=0;
            for(int c=0;c<n-2;c++)
            {
                temp+=a[i+c];
                if(temp+sum-a[i+c+1]<ans)
                ans=temp+sum-a[i+c+1];
            }
            temp=0;
            for(int c=1;c<n-1;c++)
            {
                int j=i-c;
                if(j<=0) j+=n;
                temp+=a[j];
                if(temp+sum-a[j-1]<ans)
                ans=temp+sum-a[j-1];
            }
            printf(" %lld",ans);
        }
        printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值