n人最速ブリッジ問題【java版】


【問題の説明】
n人は夜に橋を渡り、いつでも2人で1組で橋を渡り、各組に懐中電灯を1本持たなければならない.このn人の中で1つの懐中電灯しか使えないので、ある往復で懐中電灯を返却し、より多くの人が橋を渡ることができるように手配します.
人によって橋を渡る速度が異なり、各グループの速度は橋を渡るのが最も遅い人が使う時間によって決定され、n<=1000と約束され、誰もいない橋を渡る時間は100秒を超える.
【入力】
入力された最初の行はnを与え、次のn行は1人当たりのブリッジ時間を与え、1000人を超えず、誰もいないブリッジ時間は100秒を超える.
1 2 5 10
【出力】
出力された最初の行は、すべてのn人がブリッジを通過する総秒数を与え、次のいくつかの行は、実装ポリシーを与える.各行には、1つまたは2つの整数が含まれ、ブリッジを構成する1人または2人が時間で識別されることを示します.全部で:17秒で行く:1 2回:1行く:5 10回:2行く:1 2
【分析】
1回のブリッジは最大2人であり、懐中電灯は往復伝達を必要とするため、2人のメンバーがブリッジを通過することを分析単位として、ブリッジ時間を計算する.n個のメンバーをブリッジ時間の増加順にソートします.a[1]は最も速い人であり、a[2]に次いで、a[n]は最も遅い人であり、a[n-1]は最後から2番目に遅い人である.相対的な状況では、次の2つのシナリオがあります.
◆方案一:最も速いメンバーa[1]で懐中電灯を伝達して最も遅いa[n]とa[n-1]が橋を渡るのを助け、往復にかかる時間が2*a[1]+a[n]+a[n-1]であることが分かりやすい
◆シナリオ2:最も速いメンバーa[1]と次の速いメンバーa[2]で懐中電灯を伝達して最も遅いa[n]とa[n-1]が橋を渡るのを助ける.具体的なシナリオは以下の通りである.
1.a[1]とa[2]から対岸までの時間はa[2]である.
2.a[1]は、最も遅いa[n]およびa[n−1]に懐中電灯を返し、a[n]およびa[n−1]は対岸に着いた後、a[2]に懐中電灯を渡し、かかる時間は、a[1]+a[n];
       3.a[2]は戻り、使用時間はa[2]である.
シナリオ2を統合するために用いられる総時間は2*a[2]+a[n]+a[1]である.
明らかに、2つのスキームの良し悪しは彼らの総時間に依存し、2 a[1]+a[n]+a[n-1]<2 a[2]+a[n]+a[1]、すなわち第1のスキームを採用し、そうでなければ第2のスキームを採用する.私たちは毎回最も遅い2人を助けて橋を渡って、時間を累積して、最後に現れる可能性のある2つの状況:
1.対岸には2人の隊員が残り、全員橋を渡り、時間はa[2].
2.対岸には3人の隊員が残っており、最も速いメンバーで懐中電灯を渡し、最も遅いメンバーが橋を渡るのを助け、次に遅いメンバーと一緒に橋を渡る.時間はa[1]+a[n-1]+a[n]である.
ここのn=3に注意してください.
コード#コード#
package test;

import java.util.Arrays;
import java.util.Scanner;

public class NMenCrossBridge {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n,i,k;//   n,i,j,k       ,        
        int[] a=new int [1024];
        int sum=0; //     
        n=sc.nextInt();
        //    
        for(i=1;i <= n;i++)
            a[i]=sc.nextInt();

        if(n == 1){
            System.out.format(a[1]+"%n"+a[1]);
        }

        k=n;
        while(k>3)	//    
        {
            if(a[1]+a[k-1] < 2*a[2])
                sum += a[k] + a[1]*2 + a[k-1];
            else
                sum += a[2]*2+ a[1] + a[k];
            k-=2;
        }
        if(k==2)	//        
            sum+=a[2];
        else		//    3   
            sum+=a[1]+a[2]+a[3];

        System.out.println(sum);//  n       
        k=n;
        while(k>3)	//      
        {
            if(a[1]+a[k-1]<2*a[2])	//   a[1]       
            {
                System.out.format(a[1]+" "+a[k]+"%n"+a[1]+"%n"+a[1]+" "+a[k-1]+"%n"+a[1]);
            }
            else					//   a[1]、a[2]         
            {
                System.out.format(a[1]+" "+a[2]+"%n"+a[1]+"%n"+a[k]+" "+a[k-1]+"%n"+a[2]+"%n");
                k-=2;
            }

            if(k==2)
                System.out.println(a[1]+" "+a[2]);
            else
                System.out.format(a[1]+" "+a[3]+"%n"+a[1]+"%n"+a[1]+" "+a[2]);

        }
    }

}

入力:
5 1 2 4 5 10
実行結果:
22 1 2 1 10 5 2 1 4 1 1 2