乘船问题

乘船问题

有n个人,第i个人重量wi,每艘船的载重量均为C,最多可乘2人。求用多少船装载所有人的方案。
贪心策略:最轻的人与最重的人配对。

题目

有n个人,第i个人重量为wi,每艘船的最大载重量为C,且最多只能乘两个人。用最少的船装载所有人。题目保证有解。
【样例输入1】
6
5 84 85 80 84 83
85
【样例输出1】
5
【样例输入2】
3
90 45 60
90
【样例输出2】
3
【样例输入3】
5
50 50 90 40 60
100
【样例输出3】
3

分析

从最轻的人i开始考虑:如果每个人都无法和他一起坐船,则唯一的方法就是每人坐一艘船;否则,他应该选择能和他一起坐船的人中最重的一个j。这样的方法是贪心的,因为它只是让“眼前的浪费”最少。
可以用反证法证明此策略的正确性:
(1)i不与任何人同船。如果将j拉来与其同船,使用的船数<=原来的船数;
(2)i与k同船。由贪心策略,因为此时i是最轻的,j是与i匹配的人中最重的,所以w[k]<=w[j],则j加入其它船可能会使其它船超重,用的船数会变多;
综上,说明这样的贪心法不会丢失最优解。
故解题步骤:(循环过程)
(1)将所有人的重量进行排序;
(2)从当前最轻的人i开始考虑,找能跟其坐一艘船的最重的人j;
(3)比最重的人j都重的人都单独坐一个船;
需要特别注意的是:循环过程中若发现i=j,表明仅剩1人待安排,此时这个人自己一船。

代码

#include <iostream>  
#include <algorithm>  
using namespace std;  
const int maxn=1005;  
int n,C;     //n个人 船最大载重量C  
int ans=0;   //使用的最少船数   
int w[maxn]; //n个人的重量   
int main()  
{  
    int i,j;   
    cin>>n;  
    for(i=0;i<n;i++)  
        cin>>w[i];  
    cin>>C;  //预处理:n个人按重量递增排序   
 sort(w,w+n); //i.j分别用来标记待安排的最轻的人和最重的人   
    i=0,j=n-1;   //当还有人待安排时,循环   
    while(i<=j)  
    {  
 //待安排的人中最轻的人和最重的人重量之和超过船的最大载重量  
        //或者仅剩1人待安排时,j单独一船   
        if(i!=j && w[i]+w[j]>C)  
        {  
            ans++;  
            j--;  
        }   //其它情况:i和j两人同船   
        else  
        {  
            ans++;  
            i++;  
            j--;  
        }  
    }  
    cout<<ans<<endl;  
    return 0;  
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值