この質問をするために Baidu で検索しましたが、コードに関するコメントはなく、質問に対する解決策は漠然と 1 ~ 2 文だったので、この質問のコードとコメントを自分で書き留めました。
トピックの説明
ここで、m 台の機械を使用して n 個のワークを処理したいと考えています。各ワークには m 個のプロセスがあり、各プロセスは異なる指定されたマシンで完了します。各ワークの各操作には指定された処理時間があります。
各ワークの各工程を工程と呼び、jはワーク番号である1からnまでの数字、kは工程である1からmまでの数字をjkという記号で表します。例えば 2-4 という数字は、2 番目のワークの 4 番目の工程の作業を意味します。この問題では、各操作に配置順序も与えます。
例えば、n=3、m=2の場合、「1-1、1-2、2-1、3-1、3-2、2-2」が与えられた配置順序、つまり最初の配置順序となります。最初のワークピースの最初のプロセスを配置し、次に最初のワークピースの 2 番目のプロセスを配置し、次に 2 番目のワークピースの最初のプロセスを配置します。
一方で、各操作のスケジューリングは次の 2 つの制約を満たす必要があります。
(1) 同一ワークの場合、各工程は前の工程が完了した後にのみ開始できます。
(2) 各機械で同時に加工できるワークは 1 つまでです。
一方、後続の操作がスケジュールされている場合、以前にスケジュールされた操作の稼働ステータスを変更することはできません。
同じワークを工程順に配置するため、元の順序のままワーク番号を与えるだけでも同じ配置順序が得られるため、入力データではこの配置順序を「1 1 2」と略します。 3 3 2」。
「順序どおりに配置」では、各操作を指定された順序で配置することだけが必要であることにも注意してください。各マシンでの実際の操作順序は必ずしも一致するわけではありません。特定の実装中に、背面の特定の操作が前面の特定の操作より前に完了する可能性があります。
たとえば、n=3、m=2 の場合、既知のデータは次のとおりです (マシン番号/処理時間)。
次に、配置シーケンス「1 1 2 3 3 2」については、下図の両方の実装が正しいことになります。
ただし、所要時間の合計はそれぞれ 10 時間と 12 時間です。
あるマシンの隙間(稼働が予定されていないマシンの最後の部分も隙間とみなすことができます)に操作を挿入する場合、その操作は前方、後方、または中央に挿入できます。 。
問題を簡単にするために、制約 (1) と (2) を保証する条件の下で、できるだけ早く挿入するように努めることに同意します。また、挿入可能な隙間が複数ある場合には、制約(1)、(2)を確保した条件で前側の隙間に挿入することにも同意します。
したがって、これらの規則では、上の例の選択肢 1 は正しいですが、選択肢 2 は誤りです。
明らかに、これらの規則の下では、特定の配置順序に対して、この配置順序に準拠する実装計画は 1 つだけ存在します。この計画がすべてのタスクを完了するのに必要な合計時間を計算してください。
入力
行 1: スペースで区切られた 2 つの正の整数 m と n (m (<20) はマシンの数を表し、n (<20) はワークピースの数を表します): 行 2: スペースで区切られた数値 。並び順。 次の 2n 行では、各行はスペースで区切られた m 個の正の整数であり、各数値は 20 を超えません。 このうち最初のn行は各ワークの各工程で使用する号機番号を順番に表しており、最初の番号は最初の工程の号機番号、2番目の番号は2番目の工程の号機、というようになります。 最後のn行は各ワークの各工程の処理時間を順番に表しています。
出力
処理時間が最小となるのは 1 つの正の整数だけです。
コードは以下のように表示されます:
#include<bits/stdc++.h>
名前空間 std を使用します。
int m, n, ans=0;
int order[1000];//保存プロセス順序
int step[21];//step[i] はワークピースの進行中のプロセスを示し、0 に初期化され、ワークピースがまだ実行されていないことを示します。処理されたプロセス
int mac[21][10005];//mac[i][j] はマシン i の時点 j が空いているかどうかを示します
int last_time[21];//last_time[i] は処理された時刻を示しますワークiの最終工程が終了
struct node
{ int id, time; }a[21][21];//a[i][j] は、そのマシン上で i 番目のプロセスと j 番目のプロセスが実行および処理されるのに必要な時間を示します
int main()
{
//入力データ
cin>>m>>n;
for (int i=1; i<=m*n; i++) cin>>order[i];
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
cin>>a[i][j].id;
for (int i=1; i<=n; i++)
for (int j=1; j< =m; j++)
cin>>a[i][j].time;
//注文シーケンスの処理、つまり、処理の 1 項目の処理
(int i=1; i<=m*n; i++)
{ int now = order[i];//処理が必要な現在のワーク int k = ++step[now];//k は、処理が必要な現在のプロセスがワークのプロセス番号であることを示します int t = 0;//時間を割り当てることができます int id = a[now][k].id, time = a[now][k].time; //対応するマシン上の空き時間を探します for (int j=last_time[ now]+1;; j++)//今回は終了時刻であり、すでに占有されており、次の分から新しいプロセスを開始する必要があるため、1 を追加します
{ if (mac[id][j] == 0)//マシンの j 時点が占有されていない (つまり、0 に等しい) 場合、割り当て可能な時間 t++ にカウントされます。それ以外の場合は t = 0; ( t = = time)//時間が十分であれば、 { for (int p=j-time+1; p<=j; p++) mac[id][p] = 1;//t を使用しますこの時間は割り当てられています はい、1 を割り当てるということは、ID としてマシン番号を持つ時点 j がすでに占有されていることを意味します ans = max(ans, j);// 時間 j が時間軸の右端にある場合、つまり、時間 j が最大である場合、j が答えになります last_time[ now ] = j;//このワークのプロセスの終了時刻が j であることを示します Break; } } } printf("%d\n", ans ); 0 を返す; }