1. 程式人生 > >UVA690 Pipeline Scheduling 流水線排程

UVA690 Pipeline Scheduling 流水線排程

題意:給出5個工作單元,有10個完全相同的程式需要執行,工作單元要避免衝突,問所有程式執行完所需的時間最短是多少?

例:

7
X...XX.
.X.....
..X....
...X...
......X

7代表時間片,每個工作單元呼叫次數不固定,工作單元不能衝突,此資料最短時間為34。

分析:

這個只能是暴力求解,但是容易超時,我的想法就是每次列舉它的偏移量,判斷是否衝突,加上剪枝。但是超時,就算是初始化所有可能偏移量加上預期剪枝還是超時,測試資料是真的強。

超時程式碼如下:

#include<iostream>
#include<string>
#include<string.h>
#include<queue>
#include<vector>
#include<list>
#include<set>
#include<sstream>
#include<algorithm>
#include<iomanip>
using namespace std;
const int maxn = 200 + 10;
int mp[maxn],n,maxt=20000;
int tp[maxn][20+5];
int ttemp[20 + 5];
int a[maxn];
int cnt = 0, diffarray[maxn];
bool isok(int k) {
	for (int i = 0; i < 5; i++) {
		if (a[i] & (a[i] >> k))return false;
	}
	return true;
}
void dfs(int layer, int diff) {
		if (layer == 10) {
		maxt = min(diff + n, maxt);
		return;
	}
		if (diff+(10-layer)*diffarray[0] >= maxt)return;//預期判斷
		for (int k = 0 ;k<cnt; k++) {//列舉所有偏移量
			memset(ttemp, 0, sizeof(ttemp));
			int j = diff + diffarray[k];
			int ok = 1;
			for (int z = j; z < j + n; z++) {
				if (tp[z][mp[z - j]] == 1) {
					ok = 0;
					break;
				}
			}
			if (ok) {
				for (int z = j; z < j + n; z++) {
				
						tp[z][mp[z - j]] = 1;
						ttemp[z - j] = mp[z - j];
					
				}
				//memcpy(ttemp, mp, sizeof(mp));
				dfs(layer+1, j + 1);
				for (int i = 0; i < n; i++) {
					tp[j + i][ttemp[i]] = 0;
				}
			}
		}
}
int main() {
	char x;
	while (cin >> n && n) {
		int k = 1; maxt = 200000;
		memset(mp, 0, sizeof(mp));
		memset(tp, 0, sizeof(tp));
		memset(diffarray, 0, sizeof(diffarray));
		cnt = 0;
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < n; j++) {
				cin >> x;
				if (x == 'X') {
					mp[j] = i;
					tp[j][i] = 1;
					a[i] = 1 << j;//用二進位制模擬
				}
			}
		}
		for (int i = 1; i <= n; i++) {
			if (isok(i))diffarray[cnt++] = i;//儲存所有可能的偏移量
		  }
		dfs(1, 1);
		cout << maxt-1<< endl;
	}
	return 0;
}

看了大佬的二進位制模擬,真是巧妙,想不到,我用陣列一個一個判斷工作單元是否衝突,人家用二進位制直接判斷程式之間的所有工作單元是否衝突。

二進位制模擬:

#include <cstdio>
#include <cstring>
#include<iostream>
#include <algorithm>
using namespace std;

const int maxn = 25;
int n, a[5], dt[maxn], ans, cnt;

bool ok(int *p, int k) {
	for (int i = 0; i < 5; ++i)
		if (a[i] & (p[i] >> k)) return false;
	return true;
}

void dfs(int *p, int d, int sum) {
	if (sum + dt[0] * (10 - d) >= ans) return;
	if (d == 10) { ans = min(ans, sum); return; }
	for (int i = 0; i < cnt; ++i) {
		if (ok(p, dt[i])) {//直接判斷當前程式的所有工作單元和已經被佔用的工作單元是否衝突
			int p2[5];
			for (int j = 0; j < 5; ++j)
				p2[j] = (p[j] >> dt[i]) | a[j];//時間片前進,所有單元后移,沒有衝突,加上新單元
			dfs(p2, d + 1, sum + dt[i]);
		}
	}
	return;
}

int main() {
	while (cin>>n&&n) {
		memset(a, 0, sizeof(a));
		memset(dt, 0, sizeof(dt));
		char x;
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < n; j++) {
				cin >> x;
				if (x == 'X')
					a[i] |= (1 << j);//存入位置量
			}
		}
		cnt = 0;
		for (int i = 1; i <= n; ++i)
			if (ok(a, i)) dt[cnt++] = i;//找到所有可能偏移量
		ans = 10 * n;
		dfs(a, 1, n);
		cout << ans << endl;
	}
	return 0;
}