贪心问题,有两种最优方式,一种是最小次小走与最大次大走轮流的搭配,另一种是最小最大一块走的搭配,需要一定的判定条件 ~
在此给出两种不同情况的数据
第一种(样例):
4
1
2
5
10
第二种:
4
1
3
4
5
在此给出两种不同情况的数据
第一种(样例):
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;
}