您的位置:首页 > 其它

POJ 1700 & NYLG 47 过河问题(贪心 || DP)

2014-04-07 17:09 447 查看
链接 :http://poj.org/problem?id=1700

http://acm.nyist.net/JudgeOnline/problem.php?pid=47

Description
A group of N people wishes to go across a river with only one boat, which can at most carry two persons. Therefore some sort of shuttle arrangement
must be arranged in order to row the boat back and forth so that all people may cross. Each person has a different rowing speed; the speed of a couple is determined by the speed of the slower one. Your job is to determine a strategy that minimizes the time
for these people to get across.
Input
The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. The first line of each case contains
N, and the second line contains N integers giving the time for each people to cross the river. Each case is preceded by a blank line. There won't be more than 1000 people and nobody takes more than 100 seconds to cross.
Output
For each test case, print a line containing the total number of seconds required for all the N people to cross the river.
Sample Input
1
4
1 2 5 10

Sample Output
17


思路分析 :

当n=1,2,3时所需要的最小时间很容易求得,现在由n>=4,假设n个人单独过河所需要的时间存储在数组t中,将数组t按升序排序,即数组中所表示的时间是递增的.

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


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

    2> 最快的和最慢的过河,然后最快的回来,再最快的和次慢的过河,然后最快的回来.

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

    1> 方案1所需时间为:t[0]+2*t[1]+t[n-1];


    2> 方案2所需时间为:2*t[0]+t[n-2]+t[n-1];

    如果方式1优于方式2,那么有:t[0]+2*t[1]+t[n-1]<2*t[0]+t[n-2]+t[n-1] 化简得:2*t[1]<t[0]+t[n-2]

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


(注意:此题的贪心策略是动态的!!!)


代码如下:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAXN 1000 //最多人数
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;

int s[MAXN];

int cmp(const void *a, const void*b) //按时间从小到大排序
{
return *(int *)a - *(int *)b;
}

int main()
{
int cas, n, k, st, a, b;
scanf("%d", &cas);
while(cas--) {
scanf("%d", &n);
for(int i=0; i<n; ++i) {
scanf("%d", &s[i]);
}
qsort(s, n, sizeof(int), cmp);
if(n == 1 || n == 2) {
printf("%d\n", s[n-1]);
continue;
}
st = 0;
if(n % 2) { //最后一次过河所需的时间,分为奇数和偶数两种情况
st+= s[0] + s[1] + s[2];
}else {
st+= s[1];
}
k = (n - 2) / 2; //贪心的次数
for(int i=0; i<k; ++i) { //贪心的策略
a= s[0] + 2 * s[1] + s[n-1];
b= 2 * s[0] + s[n-1] + s[n-2];
if(a < b) {
st += a;
}else {
st += b;
}
n -= 2;
}
printf("%d\n", st);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DP