您的位置:首页 > 其它

NYOJ47——过河问题(贪心)

2013-04-11 19:20 274 查看
题目描述:

在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,N人所需要的时间已知;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这N人尽快过桥。

输入:

第一行是一个整数T(1<=T<=20)表示测试数据的组数

每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河

每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0<Si<=100)

输出:

输出所有人都过河需要用的最少时间

样例输入:

1

4

1 2 5 10

样例输出

17

思路分析:

那么这时将单独过河所需要时间最多的两个旅行者送到对岸去,有两种方式:

1、 最快的(即所用时间t[0])和次快的过河,然后最快的将船划回来,再次慢的和最慢的过河,然后次快的将船划回来,

2、 最快的和最慢的过河,然后最快的将船划回来,再最快的和次慢的过河,然后最快的将船划回来。

这样就将过河所需时间最大的两个人送过了河,而对于剩下的人,采用同样的处理方式,接下来做的就是判断怎样用的时间最少,

1、方案1所需时间为:t[0]+2*t[1]+t[i-1]

2、方案2所需时间为:2*t[0]+t[i-2]+t[i-1]

如果方式1优于方式2,那么有:t[0]+2*t[1]+t[i-1]<2*t[0]+t[i-2]+t[i-1] 化简得:2*t[1]<t[0]+t[i-2]。即此时只需比较2*t[1]与t[0]+t[i-2]的大小关系即可确定最小时间,此时已经将单独过河所需时间最多的两个人送过了河,那么剩下过河的人数为:i-=2,采取同样的处理方式。

如果没过河的人中,除了最快和次快的,就只剩下一个人,那么就由最快的送最慢的过河,最快的回来,最后最快的和次快的一起过河。时间为a[0]+a[i]。最后统一再加上最快和次快的过河时间。

参考代码:
#include<stdio.h>
#include<stdlib.h>

int compare(const void *a,const void *b)
{
int *p1 = (int *)a;
int *p2 = (int *)b;
return *p1-*p2;
}

int main()
{
int a[1000];
int n;
int t;
int i;
int ans;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i = 0; i < n; ++i)
scanf("%d",&a[i]);
qsort(a,n,sizeof(int),compare);

if(n < 3)
{
printf("%d\n",a[n - 1]);
continue;
}
i = n - 1;
ans = 0;
while(i > 1)
{
if(i == 2)
{
//剩一个人,则最快的把最慢的送过去
ans += a[0] + a[i];
break;
}
if(a[1] + a[1] < a[i - 1] + a[0])
ans += a[i] + a[1] + a[1] + a[0];
else
ans += a[i] + a[i - 1] + a[0] + a[0];
i -= 2;
}
//最后把最快的和最慢的送过河
ans += a[1];
printf("%d\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  贪心 ACM