题意:有连续n块内存,然后有k个文件,每个文件可以分为ki块放到内存里,其他内存块为空,现在给出每个文件的ki个碎片在内存中的放在第几块(碎片有序),然后开始进行内存块内容的移动,操作a b表示把内存a中的东西放到内存b中,前提是b为空,要求最少的操作使文件能够按顺序从最小的内存块开始存储,输出顺序操作过程。
题解:用一个flag[i] = j表示位置i上放的碎片应该放到位置j上,可以先遍历一遍把能放碎片的先放,然后开始循环,挑出一个摆放不正确的位置,把碎片放到空闲位置,然后循环遍历把能放到正确位置的碎片放到正确位置,直到全部都对。
#include <stdio.h>
#include <string.h>
const int N = 10005;
int n, k, flag[N], num;
bool judge() {
for (int i = 1; i <= num; i++)
if (flag[i] != i)
return false;
return true;
}
void solve() {
int c = 0;
while(1) {
int cc = c;
for (int i = 1; i <= num; i++) {
if (!flag[i]) {
for (int j = 1; j <= n; j++)
if (flag[j] == i) {
c++;
printf("%d %d\n", j, i);
flag[i] = i;
flag[j] = 0;
break;
}
}
}
if(c == cc)
break;
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &k);
memset(flag, 0, sizeof(flag));
int temp, a;
num = 0;
for (int i = 0; i < k; i++) {
scanf("%d", &temp);
for (int j = 0; j < temp; j++) {
scanf("%d", &a);
flag[a] = ++num;
}
}
if (judge())
printf("No optimization needed\n");
else {
solve();
while (1) {
for (int i = 1; i <= num; i++) {
if (flag[i] && flag[i] != i) {
for (int j = num + 1; j <= n; j++)
if (!flag[j]) {
printf("%d %d\n", i, j);
flag[j] = flag[i];
flag[i] = 0;
break;
}
break;
}
}
solve();
if (judge())
break;
}
}
if (t)
printf("\n");
}
return 0;
}