题目:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=71
思路:依然是贪心,一条船上最多两个人,但是人的体重不能超过船所能承受的重量。从局部到整体,局部(做一条船)前最好的方法就是一条船尽量坐两个人。把体重从小到大排序后,最重的人配一个最轻的人,体重和小于w,两人坐一条船。一直这样分配船,最后总用船后最少。
代码:
1 #include<stdio.h> 2 #include<algorithm> 3 using namespace std; 4 int main() 5 { 6 int s,w,n,a[305],i,j,c; 7 scanf("%d",&s); 8 while(s--) 9 { 10 c=0; 11 j=0; 12 scanf("%d %d",&w,&n); 13 for(i=0; i<n; i++) 14 { 15 scanf("%d",&a[i]); 16 } 17 sort(a,a+n);//升序 18 for(i=n-1; i>=0; i--) //从重的先开始坐船,看看前面有没有轻一点的人一起拼船 19 { 20 if(i<j)//已经没人了 21 break; 22 if(i==j) //只剩一个人了,不用拼船,这 个人坐一条船,并且分配船只的任务结束了 23 { 24 c++; 25 break; 26 } 27 if(a[i]+a[j]<=w)//这两个人可以拼船 28 j++;//轻的那个人拼船走了 29 c++;//一条船用完 30 } 31 printf("%d\n",c); 32 } 33 return 0; 34 }
一年前也做了这一题,相比去年思路更加清晰了,代码简洁一些,深感欣慰 ^.^,不过去年的想法也很不错,如已经坐上船的人 体重变成比 船最大承重 大一写,如w+1,这样一来避免了重复上船。如果所有人都上船了的时候,sum=n*(w+1),这个作为结束条件。代码如下:
代码:
1 #include<stdio.h> 2 int main() 3 { 4 int s,w,n,a[305],i,j,f,g,k,t,count=0,sum; 5 scanf("%d",&s);//输入要测试的次数 6 while(s--) 7 { 8 scanf("%d%d",&w,&n);//输入独木舟的最大承载重量和人数 9 f=w;//方便下面还原w 10 for(i=0; i<n; i++) 11 { 12 scanf("%d",&a[i]);//输入人的重量 13 } 14 //选择法排序(从大到小) 15 for(i=0; i<n-1; i++) 16 { 17 k=i; 18 for(j=i+1; j<n; j++) 19 { 20 if(a[j]>a[k])//找出最大数的下标 21 { 22 k=j;//标记位置 23 } 24 } 25 if(k!=i)//若最大数的下标位置不在下标位置i,则交换 26 { 27 t=a[k]; 28 a[k]=a[i]; 29 a[i]=t; 30 } 31 } 32 //求独木舟的数量 33 do 34 { 35 sum=0; 36 g=0; 37 for(i=0; i<n&&w>0; i++) 38 { 39 if(a[i]<=w) 40 { 41 w=w-a[i];//计算剩余空间 42 a[i]=f+1;//为避免重复计算 43 g++; 44 } 45 if(g==2)//一条独木舟上最多两个人 46 break; 47 } 48 w=f;//还原w 49 count++;//记录独木舟的条数 50 //求当前数组的和 51 for(i=0; i<n; i++) 52 { 53 sum=sum+a[i]; 54 } 55 } 56 while(sum!=n*(f+1)); //当数组全部替换的时候,说明游客都已坐入独木舟,退出循环 57 printf("%d\n",count); 58 count=0;//运算第二组之前,初始化独木舟数量 59 } 60 return 0; 61 }