过桥问题
原是4人过桥,ABCD要单独过桥分别需要用时1分、2分、5分、10分,过桥需要灯(只有一盏),一次只能2人一起过(意味着需要有人送灯回来),过桥时间已用时多的人为准,问如何在17分钟内让四人全部通过。
答案是A和B先过,A回来,CD再过,B回来,AB第二次过。17秒完成!
用C语言拓展成n人过桥,过桥时间自定,求过桥最短用时的方案。
对此,可以简化问题,分步解决。先解决最少时间过桥的问题。好好理解贪心法:
1)当人数<3时,直接过
2)当人数=3时,我们假设过河时间是从小到大的a,b,c (后期排列的问题易解决),显然用最小的来送灯(c+a+b<c+b+b)
3)当人数=4时,a,b,c,d(同样是升序)
Ⅰ如果用最小的来送(配合最大的过去,a回来,再陪次大的过去,回来):d+a+c+a+b=d+c+b+2a
Ⅱ如果先让最小的两个过桥,再让其中一个回来,让最大的两个过桥,再让之前留下来的那个回来,再让最小的2个过桥:b+a+d+b+b=d+3b+a
当d+c+b+2a<d+3b+a,即c-2b+a<=0时,用第一种方法,否则用第二种方法
4)当人数>4时,a,b....c,d(升序),如果让最小的来送,d+a+c+a=d+c+2a,如果先让两个最小的过桥b+b+a+d=d+2b+a.那么c-2b+a<=0时,用第一种方法。
#include<stdio.h> int time[999]; int main() { int sum=0,n=4; int time[4]={1,2,5,10}; while(n) { if(n == 1) { sum +=time[0]; break; } else if(n == 2) { sum += time[1]; break; } else if(n == 3) { sum += time[0] + time[1] + time[2]; break; } else if(n == 4) { if(time[2] + time[0] - 2 * time[1] <= 0)//用第一种方法(最大配最小过去,最小回) sum += (2 * time [0] + time[1] + time[2] + time[3]); else //方法二(两个最小过去,其中一回来,让两个最大过去) sum += (time[0] + 3 * time[1] + time[3]); break; } else { if(time[n - 2] - 2 * time[1] + time[0] <= 0) sum += (time[n - 1] + time[n - 2] + 2 * time[0]); else sum += (time[n - 1] + 2 * time[1] + time[0]); n -= 2; } } printf("%d\n", sum); return 0; }
那么之后要解决的就是包括排序在内的由用户手动给出数值,计算机给出方案。由于算法和算法判定的标准已定,接下去的就水到渠成了。
#include<stdio.h> #define MAX 100 int CrossBridge(int a[],int n) { int time; if(n==1) { time=a[0]; printf("桥左->桥右:%d\n",a[0]); return time; } else if(n==2) { time=a[1]; printf("桥左->桥右:%d,%d\n",a[0],a[1]); return time; } else if(n==3) { time=a[0]+a[1]+a[2]; printf("桥左->桥右:%d,%d\n",a[2],a[0]); printf("返回送灯->:%d\n",a[0]); printf("桥左->桥右:%d,%d\n",a[0],a[1]); return time; } else { if(2*a[1]>a[0]+a[n-2]) { time=2*a[0]+a[n-1]+a[n-2]; printf("桥左->桥右:%d,%d,\n",a[n-1],a[0]); printf("返回:%d\n",a[0]); printf("桥左->桥右:%d,%d\n",a[0],a[n-2]); printf("返回:%d\n",a[0]); } else { time=a[0]+a[1]+a[n-1]+a[1]; printf("桥左->桥右:%d,%d\n",a[0],a[1]); printf("返回:%d\n",a[0]); printf("桥左->桥右:%d,%d\n",a[n-1],a[n-2]); printf("返回:%d\n",a[0]); } return time+CrossBridge(a,n-2); } } void sort(int b[],int n) { int i,j,k,index,temp; for(i=0;i<n-1;i++) { index=i; for(j=i+1;j<n;j++) { if(b[index]>b[j]) index=j; } temp=b[i]; b[i]=b[index]; b[index]=temp; } for(k=0;k<n;k++) printf("%-3d",b[k]); } int main() { int crossnum,i; int t[MAX]; printf("请输入要过桥的人数n:"); scanf("%d",&crossnum); printf("依次输入每个人过桥所需的时间\n"); for(i=0;i<crossnum;i++) { scanf("%d",&t[i]); } printf("按升序自动排列:"); sort(t,crossnum); printf("过桥方案如下:\n"); printf("这%d人过桥的最短时间为:%d\n",crossnum,CrossBridge(t,crossnum)); return 0; }