PAT1014順番待ち「質問を正しく理解することの重要性について」

1014.順番待ち(30)

銀行がサービスのためにN個のウィンドウを開いているとします。窓の前に黄色い線があり、待合室を2つの部分に分けています。顧客が列に並んで待つためのルールは次のとおりです。

  • 各ウィンドウの前にある黄色の線の内側のスペースは、M人の顧客との線を含めるのに十分です。したがって、すべてのN行がいっぱいになると、(NM + 1)番目以降のすべての顧客は、黄色の線の後ろに並んで待つ必要があります。
  • 各顧客は、黄色の線を横切るときに待機する最短の線を選択します。同じ長さの行が2つ以上ある場合、顧客は常に最小数のウィンドウを選択します。
  • Customer [i]がトランザクションを処理するにはT [i]分かかります。
    最初のN人の顧客は、午前8時にサービスを受けるものと想定されています。

ここで、各顧客の処理時間を考慮して、顧客が彼/彼女のビジネスを行った正確な時間を伝えることになっています。

たとえば、銀行に2つのウィンドウがあり、各ウィンドウに2人の顧客が黄色の線の内側で待機しているとします。5人の顧客が、それぞれ1、2、6、4、3分かかるトランザクションを待っています。午前8時の時点で、customer1はwindow1でサービスされ、customer2はwindow2でサービスされます。Customer3はウィンドウ1の前で待機し、customer4はウィンドウ2の前で待機します。Customer5は黄色の線の後ろで待機します。

08:01に、customer1は終了し、customer5はwindow1の前のラインに入ります。Customer2は08:02に、customer4は08:06に、customer3は08:07に、最後にcustomer5は08:10に出発します。

入力仕様:

各入力ファイルには、1つのテストケースが含まれています。各ケースは、4つの正の整数を含む行で始まります:N(<= 20、ウィンドウの数)、M(<= 10、黄色の線の内側の各行の最大容量)、K(<= 1000、顧客の数) 、およびQ(<= 1000、顧客クエリの数)。

次の行には、K人の顧客の処理時間であるK個の正の整数が含まれています。

最後の行には、Qの正の整数が含まれています。これは、トランザクションを実行できる時間について尋ねている顧客を表しています。顧客には1からKまでの番号が付けられています。

出力仕様:

Qのお客様ごとに、トランザクションが終了した時刻を1行に、[08、17]と[00、59] の形式HH:MM印刷します。銀行は毎日休業しているため、 17:00以降、17:00までに対応できない顧客の場合は、代わりに「申し訳ありません」と出力する必要があります。HHMM

入力例

2 2 7 5
1 2 6 4 3 534 2
3 4 5 6 7

出力例

08:07
08:06
08:10
17:00
Sorry

  変更後、2、4、5が何回パスできなかったのかわかりません。Niu Keに行くと、合格率は0であり、正しい出力値を表示することはできませんでした(1000ゲスト、すべてではありません)が、テストケースに問題はないはずです。ACコードのコピーを見つけて、自分の出力とExcelで比較することしかできません。違いは1つだけであることがわかりました。他の人のコードは17:00以降の時間(17:05など)を出力でき、コードは、トランザクション終了時間が17ポイントを超えるすべてのトランザクションを17ポイントとして決定します。私は本当に賢い天才です!元のテキストをもう一度試してみましょう。

Note that since the bank is closed everyday after 17:00

  それは言うことです!閉店時間になり次第、本サービスを終了させて​​いただきます!だから、ドアを閉めると、人を追い払ったと思うのは、子供の頃にこのような経験をしたからです。そして、私が挙げた例は、17:00に、ゴーストが仕事を辞めて、仕事の後でも彼が仕事をしないことを知っていたときです。そして、私は長い間取引をするために銀行に行ったことがありません。私がこの質問にどれだけの時間を費やしたかを言うのは本当に恥ずかしいです。ACコードを投稿しましょう。

  一般的な考え方は、黄色の線の前にいる人を表すためにkキューqfrontを使用し、黄色の線の後ろにいる人を表すためにキューの後ろにあるキューを使用することです(キューに格納されている人の、取引に必要な時間ではなく、1-kです。本は言った:キューは構造よりも番号を格納する方が良いです。各人のトランザクションの時間と数の間の対応については、マップまたは構造を使用できます。マップを選択しました)。時間は分単位で均一に記録され、最終的に出力されるときに変換されます。

ループのたびにいくつかのことを行います。

1.ウィンドウMINの前の残り時間の最小値(つまり、qfront.front()の最小値)を見つけます
。2.次に、各ウィンドウチームの最初の要素に対応するサービス時間のMINを差し引きます。完了し、チームを離れるqfrontに対応して、qbehindの人々が追加されます(これもタイトルと同じ長さです。タイトルの最も短いキューが実際にはm-1なので、短い方が黄色を意味するため、番号が最も小さいキューが優先されます。行の後ろに誰もいない)。
3.もう1つのポイントは、マイナスマイナスの前に判断を追加することです。チームのトップにいる人のサービス終了時間が17:00以上の場合、キューはブロックされ、その後のすべてのトラバーサル(実際には、背後にいる人)には参加しません1日ブロックされます)。ブロックされている方は終了時刻がデフォルトの-1になり、時刻を切り替えると「ごめん」になります。

コードは次のとおりです。

#include <iostream>
#include <queue>
#include <map>
using namespace std;
const int maxn = 1010;
int m,n,k,q;
queue<int> qfront[21],qbehind;
string getTime(int);
map<int,int> table;
int curTime=0;//当前时间,随着每轮经历MIN时间而变化
bool flag[21];
int main(){
    scanf("%d%d%d%d", &n, &m, &k, &q);
    vector<int> times(k+1,-1);
    for(int i=1;i<=k;i++){
        int t;
        scanf("%d",&t);
        qbehind.push(i);//先把人全塞进黄线后面
        table[i]=t;
    }
    //初始化黄线前的队列
    for(int i=1;i<=n*m;i++){
        int v = i%n==0? n:i%n;
        if(!qbehind.empty()){
            qfront[v].push(qbehind.front());
            qbehind.pop();
        }
    }
    while(1){
        int MIN=0x3fffffff,u=-1;
        //找出最短的时间MIN
        for(int i=1;i<=n;i++){
            if(!qfront[i].empty() && !flag[i]){
                int v = qfront[i].front(); 
                if(table[v]<MIN){
                    MIN=table[v];
                    u=v;
                }
            }
        }
        if(u==-1) break;//所有窗口都被阻塞或完成
        //所有未被阻塞窗口经历时间MIN
        for(int i=1;i<=n;i++){
            if(!qfront[i].empty() && !flag[i]){
                int t=qfront[i].front();
                //无法在规定时间前完成服务的人会阻塞一个窗口
                if(curTime+table[t]>539){
                    flag[i]=true;
                    times[t]=curTime+table[t];
                    continue;
                }
                table[t]-=MIN;
                //MIN时间过后完成服务的人出队,黄线后的人补充队列
                if(table[t]==0){
                    qfront[i].pop();
                    times[t]=curTime+MIN;
                    if(!qbehind.empty()){
                        qfront[i].push(qbehind.front());
                        qbehind.pop();
                    }
                }
            }
        }
        curTime+=MIN;
    }
    for(int i=0;i<q;i++){
        int t;
        scanf("%d",&t);
        cout<<getTime(times[t])<<endl;
    }
    return 0;
}
string getTime(int t){
    if(t==-1) return "Sorry";
    int h=t/60+8;
    int m=t%60;
    string hh=h>9?to_string(h):"0"+to_string(h);
    string mm=m>9?to_string(m):"0"+to_string(m);
    string ans = hh+":"+mm;
    return ans;
}

要約:

  • 質問を注意深く調べ、 5分以上かけて質問の意味理解に費やすのではなく、問題を当たり前のことと考えるのではなく、穴を数回以上埋めます。
  • 私の経験によれば、この試験の例では、質問のロジックが完全に説明されていないことがよくあります。少し賢い(幸運)(気)である必要があります。最初の理解が間違いなく正しいとは思わないでください。これらのロジックの1つはACです。コード作成のロジックが明確であれば、実際には、さまざまなアイデアの実現はあまり変更する必要はありません。
  • 落ち着いて、この質問は本当のことを言うのにとても時間がかかりますが、ホーンの先端に穴が空いているのです。神経ラッキング、それはプログラムロジックの側面にあるが、間違って行くが、対象者が問題を理解して思ったことはありません、猛烈ノック簡単なキーボードを感じるようになった、トップ億点があります
元の記事を4件公開 いいね!0 訪問46

おすすめ

転載: blog.csdn.net/qq_38399914/article/details/104929576