题意:给出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;
}