这道题不难,通过它我进一步理解了dfs。其实我现在觉着dfs本质上就是递归?我看到网上有说用栈的数据结构解决这道题,但是递归本质上不就是栈嘛~
这道题的大意是,整理文件碎片,把同一个文件在磁盘上连续空间存放起来,文件之间也按照顺序存放在磁盘上。大致思路就是,从第一个磁盘空间开始捋,如果是空的就找到第一个文件片段所在的磁盘空间,清空该空间,把第一个文件片段移动到第一个磁盘空间。如果是非空就找到第一个磁盘空间里的文件片段应该在的空间,看这个空间是不是空,以此类推。如果形成了环(最后又回到了深搜的根节点。比如1号空间里是2号片段,2号空间里是1号片段,再去看1号空间,没完没了......)那么就要借助一个空的磁盘空间(就像汉诺塔......)多交换一步,腾空一个,就好啦~最后再把那个被扔到空的空间里的文件放回应该放的地方~
举个有环的简单例子,就是
1 2 3 4
2 3 1 0
算法的意思就是,1里面有2,那我找找2里面是不是空,如果是空把2文件直接放进2里,再找到1文件放到1里不就行了?可是2里面有3,那我再看看3,3里面有1,我要是再看1我就成驴拉磨了......所以我得想办法把空间3清空才能打破僵局,我把1文件放到4里,这样3空间就是空的,2里的文件3就可以移到3里,1的文件2就可以移到2里。不成环就更方便啦!
下面上代码~我现在也是个坚持写注释的好孩子啦!
#include<iostream>
#include<vector>
using namespace std;
//1.变量名不同作用域尽量避免重复
vector<int> space;//索引为磁盘空间
vector<int> clus;//索引为文件片段编号
int flag=-1;//记录当前深搜的根节点
int freespace=0;//记录放置根节点的位置
int n;//记录磁盘空间数组长度
int allcount=0;//记录文件占据磁盘的总空间
void swapspace(int a,int b,int c,int d){//交换引起的space数组操作
space[a]=b;
space[c]=d;
cout<<c<<" "<<a<<endl;
}
void dfs(int k){
if(space[k]==0){//直接把第k个文件移到第k个空间
swapspace(k,k,clus[k],0);
clus[k]=k;
return;
}
else{
if(space[k]==flag){//形成了环,例如,磁盘空间1-5文件片段号分别为5 1 2 3 4
for(int i=1;i<n+1;i++){//找空的磁盘空间
if(space[i]==0){
freespace=i;
break;
}
}
swapspace(freespace,flag,k,0);//空磁盘空间辅助交换
clus[flag]=freespace;
swapspace(k,k,clus[k],0);
clus[k]=k;
return;
}
dfs(space[k]);//没有形成环,但是当前处理的磁盘空间被占用,就递归一下占用空间文件应该占用的空间
swapspace(k,k,clus[k],0);// 处理k号空间
clus[k]=k;
return;
}
}
int main(){
int k;
cin>>n>>k;
int num=1;
for(int i=0;i<n+1;i++){
space.push_back(0);
clus.push_back(0);
}
for(int i=0;i<k;i++){//初始化
int count;
cin>>count;
allcount+=count;
for(int j=0;j<count;j++){
int temp;
cin>>temp;
space[temp]=num;
clus[num]=temp;
num++;
}
}
for(int i=1;i<allcount+1;i++){
if(space[i]!=i){
flag=i;
dfs(i);
}
}
if(flag==-1){//一直没有不满足题意的情况
cout<<"No optimization needed";
}
return 0;
}
希望自己能多点时间练算法,希望老师少布置点作业,嗯。