1. 程式人生 > >POJ 2573 Bridge 【模擬+分治】

POJ 2573 Bridge 【模擬+分治】

stream ans 通過 name -1 code 這樣的 返回 while

題目:

n人希望在晚上過河。 最多兩人可以組成一組一起過河,每組必須有手電筒。 在n個人中只有一個手電筒,所以必須安排過河順序,以便及時返回手電筒使得更多的人可以過河。
每個人的過河速度都不同; 每一組的速度由較慢成員的速度決定。 你的任務就是確定一個方案,讓所有的人在最短的時間內過河並且輸出方案。

分析:

此題其實本來是沒有思路的,但是 ,通過排序,我們發現:既然每次都得一個人傳遞手電筒,為什麽不讓最快的那個人傳呢(其實同時需要a[1],a[2]兩個人配合,詳見方案2)?又因為能者多勞,因此每次借助a[1],a[2]把最慢的兩位帶到對岸,而最快的兩位最後過河(經過簡單的貪心分析,不難看出這種決策是最優的),經排序,我們每次把

a[1],a[2],a[n-1],a[n]分成一組,使用“好學生帶壞學生的思想”,於是就有了這樣的思路:

方案1:只借助a[1]幫a[n-1],a[n]過河;

1、a[1]帶a[n]過河 ==> a[n]

2、a[1]回去 ==> a[1]

3、a[1]帶a[n-1]過河 ==> a[n-1]

4、a[1]歸還手電 ==> a[1]

總時間:a[n]+a[n-1]+2*a[1]--------?

方案2:同時借助a[1]和a[2]幫a[n-1],a[n]過河;

1、a[1]和a[2]過河 ==> a[2]

2、a[1]回去 ==> a[1]

3、a[1]把手電給a[n-1]和a[n],a[n]和a[n-1]過河 ==> a[n]

4、a[2]歸還手電 ==> a[2]

總時間:a[n]+2*a[2]+a[1]-----------?

於是每次在決策的時候只要比較?和?的大小就好啦,先決策,輸出總時間,再輸出步驟。

參考代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace
std; int n,ans=0; int a[1010]; int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; if(n==1) { printf("%d\n%d\n",a[1],a[1]); return 0; } int nn=n; sort(a+1,a+n+1); while(n>3) { if(a[1]+a[n-1]<2*a[2]) ans+=a[n]+a[1]*2+a[n-1]; else ans+=a[2]*2+a[1]+a[n]; n-=2; } if(n==2) ans+=a[2]; else ans+=a[1]+a[2]+a[3]; printf("%d\n",ans); n=nn; while(n>3) { if(a[1]+a[n-1]<2*a[2]) printf("%d %d\n%d\n%d %d\n%d\n",a[1],a[n],a[1],a[1],a[n-1],a[1]); else printf("%d %d\n%d\n%d %d\n%d\n",a[1],a[2],a[1],a[n-1],a[n],a[2]);//記住要交還手電筒 n-=2; } if(n==2) printf("%d %d\n",a[1],a[2]); else printf("%d %d\n%d\n%d %d\n",a[1],a[3],a[1],a[1],a[2]); return 0; }

POJ 2573 Bridge 【模擬+分治】