• 51Nod:独木舟问题(贪心)


    n个人,已知每个人体重,独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人。显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟?

    输入

    第一行包含两个正整数n (0<n<=10000)和m (0<m<=2000000000),表示人数和独木舟的承重。
    接下来n行,每行一个正整数,表示每个人的体重。体重不超过1000000000,并且每个人的体重不超过m。

    输出

    一行一个整数表示最少需要的独木舟数。

    输入示例

    3 6
    1
    2
    3

    输出示例

    2
    分析: 
    一个显然的策略是按照人的体重排序。

    极端化贪心策略,最重的人要上船——如果最重的人和最轻的人体重总和不超过船的承重,则他们两个占用一条船。否则(因为假设最重的人的体重也不超过船的承重了),最重的人单独占一条船。转变为(n – 1)或者(n – 2)的问题了。

    关键在于这种贪心策略是正确的。我们可以证明,最优解也可以变为这种策略。

    (1) 假设最重的人和最轻的人的体重和超过了船的承重,那么最优解中,显然也是最重的人单独占一条船,所以这种情况下最优解和贪心策略是相同的。
    (2) 假设最重的人和最轻的人的体重和没超过船的承重。
    (2.1)如果最优解中,最重的人单独占用一条船,则可以把最轻的人也放上去,这样最优解用的船数不增加。如果最轻的人占用一条船,同样我们可以把最重的人放上去,最优解船数不增。

    (2.2) 如果最优解中最重的人x和x’占用一只船(x, x’),而最轻的人y和y’占用一只船(y, y’)
    我们换成(x, y) (x’,y’)

    (x, y)显然没超过船的承重——因为我们假设就是如此。关键看(x’, y’)。

    x’ + y’<= x’ + x 因为(x’, x)没超重,所以(x’,y’)也合法。所以换一下,最优解船数也不增。这样我们就证明了如果可能把最重的人和最轻的人放在一条船上,不会影响最优解。

    反复应用这个策略,就可以把n降低为(n – 1)或者(n – 2)个人的规模,从而解决这个问题。

    一开始的思路是写出来一个函数,用递归。后来发现直接用循环判断就行,而且比写函数要简单

    AC代码:

    #include<bits/stdc++.h>
    const int maxn=10000+10;
    using namespace std;
    int main()
    {
    	int a[maxn],n,m;
    	int i,j,sum=0;
    	cin>>n>>m;
    	for(i=0;i<n;i++) cin>>a[i];
    	sort(a,a+n);
    	i=0;
    	j=n-1;
    	while(i<=j)//保证数据没有重叠 
    	{
    		if(i==j)//i=j,即:最后剩下一个人,因为其他人都上船了,所以不管他有没有超重,只能自己在一个船上 
    		{
    			sum++;
    			break;
    		}
    		if(a[i]+a[j]<=m)
    		{
    			sum++;
    			i++;
    			j--;
    		}
    		else//有一个人偏重,让这个人自己在一个船上,然后保持体重轻的(假设是A)不上船,找到一个能和他待在一个船上的人 
    		{
    			j--;//找一个体重稍微轻点的去和A放在一起,重复以上操作 
    			sum++;//重的那个人自己在一个船上 
    		}
    	}
    	cout<<sum<<"
    ";
    	return 0;
     } 

  • 相关阅读:
    Ubuntu中root用户和user用户的相互切换
    Linux扩展权限
    計蒜客/填志愿(匈牙利算法)
    計蒜課/排澇(Edmond-Karp)
    計蒜客/數正方形(dp)
    51nodcontest#24 A(xjb)
    計蒜客/节食的限制(01背包)
    計蒜客/小教官(xjb)
    atcoder#073D(枚舉)
    Educational Codeforces Round 20 C(math)
  • 原文地址:https://www.cnblogs.com/Friends-A/p/9309055.html
Copyright © 2020-2023  润新知