題意:
每個人的移動速度不一樣,兩個人走時間是以較慢那個人,一次只能兩個人走過去橋的對面,然後需要有一個人把手電筒送回來,求耗費時間最少的方法。
想法:
先將數列P排序好,時間由小到大,本題可以分為幾種情況:
- 只有一個人:直接走過去,時間為P[0]。
- 兩個人:直接走過去,時間為P[1]。
- 三個人:P[0],P[1],P[2],時間為P[1]+P[0]+P[2]
P[0] P[1]
P[0]
P[0] P[2] - 三個人以上:如果是偶數個人(例如4個人),可利用P[0],P[1]不斷將最後面兩個人送到橋的對面,這樣就回到第二點,如果是奇數個人,不斷將最後面兩個送過去就回到第三點。
將最後面兩個送到橋的對面有兩種方式,設時間最少兩人為P[0],P[1],最後面兩個人為P[X],P[Y]:
方案A(如Example): 時間為 P[1]+P[0]+P[Y]+P[1]
P[0] P[1]
P[0]
P[X] P[Y]
P[1]
方按B:時間為 P[X]+P[0]+P[Y]+P[0]
P[0] P[X]
P[0]
P[0] P[Y]
P[0]
因此每次送最後兩個人過去的時候,要比較兩種方式的時間,如果(方案A<方案B)就使用方案A,否則使用方案B。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <algorithm> | |
using namespace std; | |
int main() | |
{ | |
// freopen("input.txt","rt",stdin); | |
int Case,N,P[1001],i; | |
scanf("%d",&Case); | |
while (Case--) | |
{ | |
scanf("%d",&N); | |
for (i=0; i<N; i++) scanf("%d",&P[i]); | |
sort (P,P+N); | |
int sum=0; | |
for (i=N-1; i>=3; i-=2){ //三個人以上 | |
int A = P[1]+P[0]+P[i]+P[1]; | |
int B = P[i]+P[0]+P[i-1]+P[0]; | |
if (A<B) sum += A; | |
else sum += B; | |
} | |
if (i == 2) sum += (P[1]+P[0]+P[2]); //三個人 | |
else if (i == 1) sum += P[1]; //兩個人 | |
else if (i == 0) sum += P[0]; //一個人 | |
printf("%d\n",sum); | |
for (i=N-1; i>=3; i-=2){ | |
int A = P[1]+P[0]+P[i]+P[1]; | |
int B = P[i]+P[0]+P[i-1]+P[0]; | |
if (A<B) printf("%d %d\n%d\n%d %d\n%d\n",P[0],P[1],P[0],P[i-1],P[i],P[1]); | |
else printf("%d %d\n%d\n%d %d\n%d\n",P[0],P[i-1],P[0],P[0],P[i],P[0]); | |
} | |
if (i == 2) printf("%d %d\n%d\n%d %d\n",P[0],P[1],P[0],P[0],P[2]); | |
else if (i == 1) printf("%d %d\n",P[0],P[1]); | |
else if (i == 0) printf("%d\n",P[0]); | |
if (Case) printf("\n"); | |
} | |
return 0; | |
} |
沒有留言:
張貼留言