这个题就是要求整理碎片的最小步数,主要考虑2种情况:
1、需要移动的位置为空,对于这种情况直接移动即可。
2、要移动到的位置构成环,对于这种情况我们要破除环,即先从最后向前找一个空位,将它放进去,再进行移位操作。
都交给递归吧~
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=11000;
int n,k,m,cnt,now[maxn];
bool vis[maxn],flag;
void DFS(int index)
{
if(!now[now[index]])
{
printf("%d %d\n",index,now[index]);
now[now[index]]=-1;
now[index]=0;
return ;
}
if(vis[now[now[index]]])
{
for(int i=n;i>0;i--)
if(!now[i])
{
printf("%d %d\n",index,i);
now[i]=now[index];
now[index]=0;
return;
}
}
DFS(now[index]);
printf("%d %d\n",index,now[index]);
now[now[index]]=-1;
now[index]=0;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
cnt=1,flag=0;
memset(now,0,sizeof(now));
for(int i=1;i<=k;i++)
{
scanf("%d",&m);
for(int j=0;j<m;j++)
{
int val;
scanf("%d",&val);
now[val]=cnt++;
if(val==cnt-1)
now[val]=-1;
}
}
for(int i=1;i<=n;i++)
{
if(now[i]&&now[i]!=-1)
{
memset(vis,0,sizeof(vis));
flag=1;
vis[i]=1;
DFS(i);
}
}
if(!flag)
printf("No optimization needed\n");
}
return 0;
}