POJ-1700 &&NYOJ 47 过河问题【贪心】

链接:NYOJ:click here POJ:click here

题意:

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

思路

贪心思想(一般都是先排序)

每次从此岸到对岸移动的两个人要么这两个人中有一个是时间最快的那个人,要么这两个人到达对岸后再也不回来。即:要么最快+最慢(最快回来换人),要么最慢+次慢(不回来)。

1.对N个人过河时间从小到大排序。cost[i];

2.分情况讨论:

⑴当n = 1,直接过河。sum = cost[0]

(2)当n = 2,直接过河。 sum = cost[1]

(3)当n = 3,无论怎么过河, sum = cost[0] + cost[1] + cost[2]

(4)当n = 4,设从小到大排序后位a=cost[0],b=cost[1],c=cost[2],d=cost[3];

用最小的来送:b + a + c + a + d =2*a+b+c+d= 2*cost[0] + cost[1] + cost[2] + cost[3](a,b过去,a回来,a,c过去,a回来,a,d过去)

两小送两大:b + a + d + b + b =a+3*b+d= cost[0] + 3*cost[1] + cost[3](a,b过去,a回来,c,d过去,b回来,a,b过去)

所以sum = min(2a + b + c + d, a + 3b + d)

(5)当n > 4,设从小到大排序后位a,b,……,c,d,大于4个人,a,b是最小的两个人,c,d是最大的两个人,目标就是把最大的两个人送过去。就要牺牲最小的。

用最小的来送:A=d + a + c + a = 2a + c + d=2*cost[0]+cost[2]+cost[3](a,d过去,a回来,a,c过去,a回来)

两小送两大:B= b + a + d + b = a + 2b + d=cost[0]+2*cost[1]+cost[3];(a,b过去,a回来,c,d过去,b回来)

循环:sum = min(A,B),直到n <= 4时候结束。

思路理解清晰,代码不难实现:

//NYOJ 47 过河问题:
//POJ 1007

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int cost[1010];
int main()
{
    //freopen("1.txt","r",stdin);
    //freopen("2.txt","w",stdout);
    int ncase,m,n,i,j;
    int sum;
    scanf("%d",&ncase);
    while(ncase--)
    {
        sum=0;
        scanf("%d",&m);
        memset(cost,0,sizeof(cost));
        for(i=0; i<m; i++)
            scanf("%d",&cost[i]);
        sort(cost,cost+m);
        while(m)
        {
            if(m==1)
            {
                sum+=cost[0];
                break;
            }
            else if(m==2)
            {
                sum+=cost[1];
                break;
            }
            else if(m==3)
            {
                sum+=(cost[0]+cost[1]+cost[2]);
                break;
            }
            else if(m==4)
            {
                if(m==4)
                    sum +=min(2*cost[0]+cost[1]+cost[2]+cost[3],cost[0]+3*cost[1]+cost[3]);
                break;
            }
            else
            {
                //if(cost[m-2]-2*cost[1]+cost[0]<=0)
                //sum+=min(cost[m-1]+cost[m-2]+2*cost[0],)
                sum+=min(cost[m-1]+cost[m-2]+2*cost[0],cost[m-1]+2*cost[1]+cost[0]);
                m-=2;
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}
时间: 2024-10-05 13:10:40

POJ-1700 &&NYOJ 47 过河问题【贪心】的相关文章

nyoj 47 过河 过河问题 【贪心】

经典贪心: 两种方案:一:让最快的和次最快的先过去,最快的回来,然后最慢的和次最慢的过去,次最快的回来a[0]+a[1]+a[1]+a[n-1] 二:最快的和最慢的过去,最快的回来,最快的和当前最慢的过去,最快的回来.a[0]+a[n-1]+a[0]+a[n-2] 每次取最优解. 注意:最后剩余没过的人小于等于3的时候,要特殊判断. 代码: #include <cstdio> #include <cstring> #include <algorithm> #define

nyoj 47——过河问题——————【贪心】

过河问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边.如果不借助手电筒的话,大家是无论如何也不敢过桥去的.不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过.如果各自单独过桥的话,N人所需要的时间已知:而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间.问题是,如何设计一个方案,让这N人尽快过桥. 输入 第一行是一个整数T(1<=T<=20)表示测试数据的组数每组测

nyoj 47 过河问题

过河问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边.如果不借助手电筒的话,大家是无论如何也不敢过桥去的.不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过.如果各自单独过桥的话,N人所需要的时间已知:而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间.问题是,如何设计一个方案,让这N人尽快过桥. 输入 第一行是一个整数T(1<=T<=20)表示测试数据的组数每组测

NYOJ 47过河问题

主要思路:先排序.有两种可能是最小的情况,一种是让最小的去带着最大的过去,然后最小的再回来,还有一种就是先最小的和第二小的一块过去, 然后最小的回来,让最大的和第二大的过去,接着第二小的回来,第二小和最小的接着在过去,最小的接着回来,主要就是这两种,用的时候判断一下,接着的问题就是n是奇数还是偶数的问题 排完序之后的a[0]最小, a[n-1]最大,第一种的时间为a[0] + a[n -1] + a[0] + a[n - 2];其中a[0]是最短的时间,a[n-1]是最大的时间,下面一样, 第二

POJ 1700 经典过河问题(贪心)

POJ题目链接:http://poj.org/problem?id=1700 N个人过河,船每次最多只能坐两个人,船载每个人过河的所需时间不同,问最快的过河时间. 思路: 当n=1,2,3时所需要的最小时间很容易求得,现在由n>=4,假设n个人单独过河所需要的时间存储在数组t中,将数组t按升序排序,那么 这时将单独过河所需要时间最多的两个旅行者送到对岸去,有两种方式: 1> 最快的(即所用时间t[0])和次快的过河,然后最快的将船划回来,再次慢的和最慢的过河,然后次快的将船划回来. 即所需时间

POJ 1700 Crossing River(贪心)

V - Crossing River Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1700 Description A group of N people wishes to go across a river with only one boat, which can at most carry two persons. There

POJ 3069 Saruman&#39;s Army (贪心)

题目大意:直线上有N个点,点i的位置是Xi,从这N个点中选取若干,给他们加上标记,对每一个点,其距离为R以内的区域内必须有被标记的点.求至少需要多少个点被标记. 题目思路:设最左边的点:点p的坐标为x,那么离其距离为R的点的坐标为(x+R),我们应该标记的点应为坐标最接近且小于等于(x+R)的点p,则此时[x,p+R]范围内点点均被标记.依次进行下去,直到包含所有点为止. #include<stdio.h> #include<queue> #include<iostream&

POJ 3069 Saruman&#39;s Army (简单贪心)

Saruman's Army Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5343   Accepted: 2733 Description Saruman the White must lead his army along a straight path from Isengard to Helm's Deep. To keep track of his forces, Saruman distributes se

poj 1827 A Bunch Of Monsters 贪心(并查集优化)

Description Background Jim is a brave explorer. One day, he set out for his next destination, a mysterious hill. When he arrived at the foot of the hill, he was told that there were a bunch of monsters living in that hill, and was dissuaded from cont