微軟面試題題目大意:有A、B、C、D四個人,要在夜里過一座橋。他們通過這座橋分別需要耗時1、2、5、10分鍾,只有一支手電,並且同時最多只能兩個人一起過橋。
請問,如何安排,能夠在17分鍾內這四個人都過橋?
四個人A(1分鍾),B(2分鍾),C(5分鍾),D(10分鍾)
第一趟:A,B過橋,A(或B)返回;(此趟花費 3(或 4)分鍾!)
第二趟:C,D過橋,B(或A)返回;(此趟花費12(或11)分鍾!)
第三趟:A,B過橋;過橋完畢。 (此趟話費 2分鍾!)
總時間17分鍾。
附:這道題本是ACM世界里的一道編程題(POJ2573),原題是有N個人過橋(場景和上面的一樣),他們通過的時間分別是a[1…n],求他們過橋的最短時間。
這道題有了上面的例子,讀者不難想到:
當人數變多的時候,每次先送最慢的兩個人過橋(最快的兩個人作為領導者,跑得快嘛,姑且就作為跑腿的)
左移每次過橋必定有兩種過橋辦法:
(假設X,Y為最慢和次慢的過橋者,x,y為最快和次快的過橋者。)
A:用最快的X陪同最慢和次慢的x,y過橋。
也就是第一步x,X過橋,x回頭(花費x+X分鍾);
第二步x,Y過橋,x回頭(花費Y+x分鍾);
這種方式一次花掉2*x+X+Y分鍾。
B:用最快和次快的x,y陪同最慢和次慢的X,Y過橋。
也就是第一步x,y過橋,x回頭(花費x+y分鍾);
第二步X,Y過橋,y回頭(花費X+y分鍾);
這種方式一次花掉x+2*y+X分鍾。
顯然上面的兩種方法,當2*x+X+Y<x+2*y+X的時候,選A否則選B過橋。
如此過橋之后,最后的情況就必然是只剩下兩個人或者三個人沒有過橋,一個一個的看:
當剩下兩個人的時候(其實就是x,y),兩個人一起過橋,花費y分鍾。
當剩下三個人的時候(其實就是x,y,另一個假設為z),此時x,z先過,x回來,x,y再過去,一共花費x+y+z分鍾。
到此處這個題目已經完全可以解出來了,不過在編代碼的時候,大家一定要注意,當1,2,3個人的時候,一定要輸出過橋的最短時間和過橋的方式,缺一不可,不然會讓你WA到想哭。
好了說這么多,讀者自己去思考吧,貼上代碼:

1 #include<stdio.h> 2 #include<algorithm> 3 using namespace std; 4 int n,a[10020]; 5 void init() 6 { 7 scanf("%d",&n); 8 for(int i=1;i<=n;i++) 9 scanf("%d",&a[i]); 10 sort(a+1,a+n+1); 11 } 12 int slove1(int k) 13 { 14 if(k<3) return a[k]; 15 if(k==3) return a[1]+a[2]+a[3]; 16 int minute; 17 if(a[k-1]+a[1]<2*a[2]) minute=2*a[1]+a[k]+a[k-1]; 18 else minute=2*a[2]+a[1]+a[k]; 19 minute+=slove1(k-2); 20 return minute; 21 } 22 void slove2(int k) 23 { 24 if(k==1) {printf("%d\n",a[1]);return ;} 25 if(k==2) {printf("%d %d\n",a[1],a[2]);return ;} 26 if(k==3) {printf("%d %d\n%d\n%d %d\n",a[1],a[3],a[1],a[1],a[2]);return ;} 27 if(a[k-1]+a[1]<2*a[2]) printf("%d %d\n%d\n%d %d\n%d\n",a[1],a[k],a[1],a[1],a[k-1],a[1]); 28 else printf("%d %d\n%d\n%d %d\n%d\n",a[1],a[2],a[1],a[k-1],a[k],a[2]); 29 slove2(k-2); 30 } 31 int main() 32 { 33 init(); 34 if(n==0) {printf("0\n");return 0;} 35 printf("%d\n",slove1(n)); 36 slove2(n); 37 return 0; 38 }