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
Sample Output
思路分析 :
当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;
}
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;
}
相关文章推荐
- POJ-1700 &&NYOJ 47 过河问题【贪心】
- nyoj-47-过河问题&&poj-1700-Crossing River
- poj 1700 Crossing River && nyoj 47 过河问题
- nyoj-47-过河问题|POJ-1700-Crossing River
- 贪心-POJ 1700 过河问题
- poj 1700 Crossing River(贪心·dp)
- POJ 1700 经典过河问题(贪心)
- POJ 1700 经典过河问题(贪心)
- POJ-1700 过河问题【贪心】
- POJ - 1700 Crossing River解题报告(过河问题的贪心策略)
- POJ-1700 过河问题【贪心】
- poj 1700 Crossing River 过河问题。贪心
- 南阳47 过河问题(经典贪心)
- POJ 1321 棋盘问题(DFS & 状压DP)
- 贪心算法之——过河问题(nyoj47)
- HDU - 1003 - Max Sum && POJ - 1050 - To the Max (经典DP问题)
- NY 47 过河问题【贪心】
- nyoj 47 过河问题 贪心
- NYOJ47——过河问题(贪心)
- poj 2573 Bridge(贪心:过河问题)