当前位置: 代码迷 >> 综合 >> POJ 1700 Crossing River (贪心)
  详细解决方案

POJ 1700 Crossing River (贪心)

热度:13   发布时间:2024-01-15 05:08:47.0

http://poj.org/problem?id=1700
题目大意:有n个人要过一条河,每个人过河都需要一个时间,有一艘船,每次过河只能最多装两个人。两个人划船过河所需的时间都取决于过河时间长的那个人,安排一个过河方案,让所有人用最短的时间全部过河。
贪心中经典的过河问题,说实话不看学长的PPT真不会。。。
首先显然要排个序。
n==1和n==2的情况很显然一次过去就完了;
n==3的情况也很显然,a[1]和a[3]过去,a[1]回来,a[1]和a[2]在过去,总共要花a[1]+a[2]+a[3];
然后考虑n==4的情况,假设四人1-4分别是a,b,c,d,这里就有两种可选方案:
1. 过河顺序为:ac、a、ad、a 时间消耗:t1=2a+c+d
2. 过河顺序为:ab、a(b)、cd、b(a) 时间消耗:t2=a+2b+d
因为t1?t2=a+c?2b,所以选择两种方案的哪一种,和a+c?2b的值有关;
这样不管n等于几,每次可以选第1,2个和第n,n-1个通过以上比较选择更优的方案将第n和n-1个人送过河,直到送到只剩2或3人,参见前面的情况。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
int a[1010],T,n;
int main()
{scanf("%d",&T);while(T--){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);sort(a+1,a+1+n);if(n==1||n==2){printf("%d\n",a[n]);continue;}if(n==3){printf("%d\n",a[n]+a[n-1]+a[1]);continue;}int p=a[1],q=a[2],r=n-1,s=n,ans=0;while(1){if(r==1&&s==2){ans+=a[2];break;}if(r==2){ans+=a[3]+a[2]+a[1];break;}if(p-2*q+a[r]<0){ans+=2*p+a[s]+a[r];s-=2;r-=2;}else{ans+=p+2*q+a[s];s-=2;r-=2;}} printf("%d\n",ans);} return 0;
}