這題關鍵是數據量太大,如果用普通的銀行家算法,最壞情況下時間複雜度爲O(N*N*M),顯然會超時。正確的解法是對每種資源分別考慮,建立M個隊列。進程對每種資源的需求數量從小到大存入隊列,這樣每次只需檢查隊列頭部的進程即可。排序時間複雜度O(M*N*logN),每個進程至多出隊M次,時間複雜度爲O(N*M*M)。
由於杭電的數據太弱,所以這個算法體現不出效果...
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <memory.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <iostream>
#include <sstream>
using namespace std;
int allo[3][50005], reqs[3][50005], avai[3], indx[3];
pair<int, int> queu[3][50005];
bool flag[3][50005];
int n, m;
int main() {
int i, j, k, cunt;
bool sign;
while (scanf("%d %d", &n, &m) != EOF) {
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
scanf("%d", &allo[i][j]);
for (i = 0; i < m; i++)
for (j = 0; j < n; j++) {
scanf("%d", &reqs[i][j]);
queu[i][j].first = reqs[i][j];
queu[i][j].second = j;
}
for (i = 0; i < m; i++)
scanf("%d", &avai[i]);
for (i = 0; i < m; i++)
sort(queu[i], queu[i] + n);
sign = true;
cunt = 0;
memset(indx, 0, sizeof(indx));
memset(flag, 0, sizeof(flag));
while (sign) {
sign = false;
for (i = 0; i < m; i++) {
for (j = indx[i]; j < n; j++) {
if (queu[i][j].first > avai[i])
break;
flag[i][queu[i][j].second] = true;
for (k = 0; k < m; k++) {
if (!flag[k][queu[i][j].second])
break;
}
if (k == m) {
sign = true;
cunt++;
for (k = 0; k < m; k++) {
avai[k] += allo[k][queu[i][j].second];
if (avai[k] > 1000000000)
avai[k] = 1000000000;
}
}
}
indx[i] = j;
}
}
if (cunt == n) puts("Yes");
else puts("No");
}
return 0;
}