题意:磁盘有n个块,有m个文件,每个文件被分割为多个块分散在磁盘中,现进行磁盘整理,要求使用最少的移动次数,使得第1个文件占用1,2,3..f1个块,第2个文件占用f1+1,f1+2...f1+f2个块。
算法:模拟,使用dfs实现
#include <iostream>
#include <string.h>
using namespace std;
int move[10010]; // move[i]=j: i-->j
int cluster[10010]; // cluster[i]=j: 第i个要处理的是j号块
bool vis[10010];
int N,K,S;
void dfs(int k)
{
int l = move[k]; // k-->l
vis[k] = true;
// 若l空闲
if (move[l] == 0)
{
cout << k << " " << l << endl;
move[l] = l;
move[k] = 0;
}
else
{
if (vis[l])
{
// 若存在环,破之
for (int i=N; i>=1; i--)
{
if (move[i] == 0)
{
cout << k << " " << i << endl;
move[i] = l; // i-->l
move[k] = 0; // 第k个cluster空余
cluster[l]=i; // 第l个要处理的cluster由k改为i
break;
}
}
}
else
{
// 递归将l移走
dfs(l);
// 将l移走后,再k-->l
cout << k << " " << l << endl; // k-->l
move[k] = 0;
move[l] = l;
}
}
}
int main()
{
while(scanf("%d%d",&N,&K)!=EOF)
{
memset(move,0,sizeof(move));
int cnt = 0;
bool needed = false;
for (int i=0; i<K; i++)
{
cin >> S;
int t;
for (int j=0; j<S; j++)
{
cin >> t;
move[t] = ++cnt; // t-->cnt
cluster[cnt]=t;
if (t != cnt)
{
needed = true;
}
}
}
if (!needed)
{
cout << "No optimization needed" << endl;
continue;
}
for (int i=1; i<=cnt; i++)
{
if (move[i] != i)
{
memset(vis,false,sizeof(vis));
dfs(cluster[i]);
}
}
}
}