贪心算法练习:乘船问题

/*--------------------------------------------------------------
有n个人,第i个的重量为wi,每艘船的最大载重为c,
而且最多只能乘两个人。用最少的船装载所有人。

输入:
第一行两个整数n和c
第二行n个整数,分别是wi

输出:
第一行输出使用船的数量num
 第二行到第n+1行每行输出两个数, 分别“人的编号”以及他所乘坐的“船的编号”。
 人的编号按输入的顺序从1到n编号。船的编号从1开始编号。
 第2行到第n+1行按人的编号从小到大的顺序输出。

思路:
考虑最轻的一个人i,他应该和谁一起坐船?假如每个人都无法和他一起坐船,
则唯一的方案就是每个人做一艘船了。否则,他应该选择能与他一起乘船的人
中最重的一个j。这样的方法是贪心的,他能保证“眼前”的浪费是最少的。 

所以,程序中先按体重排序,然后只需用i和j分别表示当前考虑的最轻的人和最重的人。
每次将j往左移动,直到i和j可以一起乘坐一艘船,然后i加1,j减1,并重复上述操作。

时间复杂度主要取决于排序。因为上述扫描的复杂度是O(n)级别。
----------------------------------------------------------------*/

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 struct person
 4 {
 5     int id;//人的编号
 6     double weight;
 7     int shipID;//船的编号
 8 };
 9 int cmpQsort1(const void *a,const void *b);//按照struct person 的weight比较a和b的大小。正方向比较。
10 int cmpQsort2(const void *a,const void *b);//按照struct person 的id比较a和b的大小。正方向比较。
11 int main()
12 {
13     int n,c,i,j,t;//t表示正要分配给第i个人的船的编号
14     int flag=0;//表示没有人体重超重,以至于无法单独乘坐一条船。
15     struct person *a;
16     freopen("5.in","r",stdin);
17     scanf("%d%d",&n,&c);
18     a=(struct person *)malloc(sizeof(struct person)*n);
19     for(i=0;i<n;i++)
20     {
21         scanf("%lf",&a[i].weight);
22         a[i].id=i+1;
23         a[i].shipID=0;
24     }
25     qsort(a,n,sizeof(struct person),cmpQsort1);
26     t=1;
27     for(i=0,j=n-1;i<=j;i++,j--) // 注意分析这里的i<=j.
28     {
29         if(a[i].weight>c)
30         {
31             printf("输入错误!有部分人体重太大,即便是自己一个人坐一条船也坐不下呵呵……\n");
32             flag=1;//表示已经发现有人因为体重太大以至于无法单独乘坐一条船。
33             break;
34         }
35         else
36         {
37             a[i].shipID=t;
38             while(a[i].weight+a[j].weight>c&&j>i) j--;
39             a[j].shipID=t;
40             t++;
41         }
42     }
43     if(flag==0)
44     {
45         for(;i<n;i++)//为那些只能考虑单独乘坐一条船的人编排他们乘船的船号
46         {
47             if(a[i].shipID==0)//如果这个人还没有编排船号
48             {
49                 if(a[i].weight<c)
50                 {
51                     a[i].shipID=t;
52                     t++;
53                 }
54                 else
55                 {
56                     printf("输入错误!有部分人体重太大,即便是自己一个人坐一条船也坐不下呵呵……\n");
57                     flag=1;//表示已经发现有人因为体重太大以至于无法单独乘坐一条船。
58                     break;
59                 }
60             }
61         }
62         if(flag==0)
63         {
64             qsort(a,n,sizeof(struct person),cmpQsort2);
65             printf("%d\n",t-1);
66             for(i=0;i<n;i++)//输出结果
67             {
68                 printf("%-8.2lf %-3d %-3d\n",a[i].weight,a[i].id,a[i].shipID);
69             }
70         }
71     }
72     free(a);
73     return 0;
74 }
75 int cmpQsort1(const void *a,const void *b)//按照struct person 的weight比较a和b的大小。正方向比较。
76 {
77     double t=((struct person *)a)->weight - ((struct person *)b)->weight;
78     if(t> 1e-5) return 1;
79     else if(t< (-1e-5)) return -1;
80     else return 0;
81 }
82 int cmpQsort2(const void *a,const void *b)//按照struct person 的id比较a和b的大小。正方向比较。
83 {
84     int t=((struct person *)a)->id - ((struct person *)b)->id;
85     if(t> 1e-5) return 1;
86     else if(t< (-1e-5)) return -1;
87     else return 0;
88 }

运行案例
输入:

10 150
80
89
70
30
45
100
120
50
120
40

输出:

6
80.00 1 4
89.00 2 3
70.00 3 5
30.00 4 1
45.00 5 3
100.00 6 2
120.00 7 1
50.00 8 4
120.00 9 6
40.00 10 2
请按任意键继续. . .

贪心算法练习:乘船问题,布布扣,bubuko.com

时间: 2024-10-18 21:49:00

贪心算法练习:乘船问题的相关文章

贪心算法之乘船问题

有n个人,第i个人的重量为w[i],每艘船的最大载重量均为c,且最多只能乘两个人.用最少的船装载所有人. 思路:从最轻的开始考虑,让最轻的和最重的一条船,若超出重量则可判定最重的只能一人一条船 代码: #include <iostream> #include <algorithm> using namespace std; int n,m; int a[100]; int main() { cin>>n>>m;//n为人数,m为一条船的最大承重 for(in

POJ1017 Packets(贪心算法训练)

Time Limit: 1000MS          Memory Limit: 10000K          Total Submissions: 51306          Accepted: 17391 Description A factory produces products packed in square packets of the same height h and of the sizes 1*1, 2*2, 3*3, 4*4, 5*5, 6*6. These pro

贪心算法的简述与示例

贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯.能够用贪心算法求解的问题一般具有两个重要特性:贪心选择性质和最优子结构性质. 参考:http://babybandf.blog.163.com/blog/static/61993532010112923767/ [例1]删数问题[B][/B] 试题描

算法导论——lec 13 贪心算法与图上算法

之前我们介绍了用动态规划的方法来解决一些最优化的问题.但对于有些最优化问题来说,用动态规划就是"高射炮打蚊子",采用一些更加简单有效的方法就可以解决.贪心算法就是其中之一.贪心算法是使所做的选择看起来是当前最佳的,期望通过所做的局部最优选择来产生一个全局最优解. 一. 活动选择问题 [问题]对几个互相竞争的活动进行调度:活动集合S = {a1, a2, ..., an},它们都要求以独占的方式使用某一公共资源(如教室),每个活动ai有一个开始时间si和结束时间fi ,且0 ≤ si &

五大常用算法之三贪心算法

贪心算法 贪心算法简介: 贪心算法是指:在每一步求解的步骤中,它要求"贪婪"的选择最佳操作,并希望通过一系列的最优选择,能够产生一个问题的(全局的)最优解. 贪心算法每一步必须满足一下条件: 1.可行的:即它必须满足问题的约束. 2.局部最优:他是当前步骤中所有可行选择中最佳的局部选择. 3.不可取消:即选择一旦做出,在算法的后面步骤就不可改变了. 贪心算法案例: 1.活动选择问题  这是<算法导论>上的例子,也是一个非常经典的问题.有n个需要在同一天使用同一个教室的活动a

零基础学贪心算法

本文在写作过程中参考了大量资料,不能一一列举,还请见谅.贪心算法的定义:贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解.贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关.解题的一般步骤是:1.建立数学模型来描述问题:2.把求解的问题分成若干个子问题:3.对每一子问题求解,得到子问题的局部最优解:4.把子问题的局部最优

贪心算法

一,贪心算法的设计思想 ? 从问题的某一个初始解出发逐步逼近给定的目标,每一步都作一个不可回溯的决策,尽可能地求得最好的解.当达到某算法中的某一步不需要再继续前进时,算法停止. 二,贪心算法的基本性质 1)贪心选择性质 所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到.这是贪心算法可行的第一个基本要素,也是贪心法与动态规划法的主要区别. 2) 最优子结构性质 该问题解的整体最优性依赖于其局部子问题解的最优性.这种性质是可以采用贪心算法解决问题的关键特征.例如

算法导论----贪心算法,删除k个数,使剩下的数字最小

先贴问题: 1个n位正整数a,删去其中的k位,得到一个新的正整数b,设计一个贪心算法,对给定的a和k得到最小的b: 一.我的想法:先看例子:a=5476579228:去掉4位,则位数n=10,k=4,要求的最小数字b是n-k=6位的: 1.先找最高位的数,因为是6位数字,所以最高位不可能在后5位上取到(因为数字的相对顺序是不能改变的,假设如果取了后五位中倒数第5位的7,则所求的b就不可能是6位的了,最多也就是4位的79228)理解这点很重要!所以问题变成从第1位到第k+1(n-(n-k-1))取

高级算法——贪心算法(找零问题)

function makeChange(origAmt, coins) {//贪心算法——找零问题 var remainAmt ; if (origAmt % .25 < origAmt) { coins[3] = parseInt(origAmt / .25); remainAmt = origAmt % .25; origAmt = remainAmt; } if (origAmt % .1 < origAmt) { coins[2] = parseInt(origAmt / .1); r