UVa 10037 - Bridge

29 篇文章 0 订阅
贪心问题,有两种最优方式,一种是最小次小走与最大次大走轮流的搭配,另一种是最小最大一块走的搭配,需要一定的判定条件 ~
在此给出两种不同情况的数据
第一种(样例):

4
1
2
5
10
第二种:
4
1
3
4
5

代码如下

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>

using namespace std;

int cmp(const void *a, const void *b)
{
    return *(int*)a > *(int*)b ? 1 : -1;
}
int a[1002], c[10000];
int main()
{
#ifdef test
    freopen("in.txt", "r", stdin);
#endif
    int num, t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &num);
        int cnt = 0, sum = 0;
        for(int i = 0; i < num; i++)
            scanf("%d", &a[i]);
        if(num != 1)
        {
            qsort(a, num, sizeof(a[0]), cmp);
            for(int j = num - 1; j > 1;)
            {
                if(a[j - 1] + a[0] > a[1] * 2)  // 判定条件:如果次大和最小的和大于次小的两倍的话,走第一种情况
                {
                    c[cnt++] = a[0];
                    c[cnt++] = a[1];
                    sum += a[1];
                    c[cnt++] = a[0];
                    sum += a[0];
                    c[cnt++] = a[j - 1];
                    c[cnt++] = a[j];
                    sum += a[j] + a[1];
                    c[cnt++] = a[1];
                    j -= 2;
                }
                else             // 否则走第二种
                {
                    c[cnt++] = a[0];
                    c[cnt++] = a[j--];
                    sum += a[j + 1] + a[0];
                    c[cnt++] = a[0];
                }
            }
            c[cnt++] = a[0];
            c[cnt++] = a[1];
            sum += a[1];
            printf("%d\n",sum);
            for(int i = 0, j = 0; i < cnt; j++)
                if(j % 2)
                    printf("%d\n", c[i++]);
                else
                {
                    printf("%d %d\n", c[i], c[i + 1]);
                    i += 2;
                }
        }
        else             // 注意只有一个人过桥的情况要特殊处理,因为这个WA了两遍还耽误了很多时间,感觉特别亏
            printf("%d\n%d\n", a[0], a[0]);
        if(t)
            puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值