Bandwidth(爆搜)

这是一道暴力都能过的题,重点其实在于理解题意,输入过程也有一点繁琐。

1.题意

先给定一个无向图,要重新安排结点的顺序,使得相邻的节点在排列中的最大距离最小

2.Solution

明显的爆搜,难就难在如何建模,其实只要把出现过的字符放到一个数组记录起来,然后搜索的时候依次安排每个节点的字母

分块讲解:

(1)输入

//首先我们可以先把":"前面的字符提出来作为u,再在:后面的字符拿出来做v
//Coder-cjh
void init(){
    mind=1e9;tot=0; 
    memset(v,0,sizeof(v));
    memset(id,0,sizeof(id));
    memset(can,0,sizeof(can));//多测不清空,爆零两行泪
    for(int i=0;i<s.size();i++)
     if(isalpha(s[i]))
      if(!id[s[i]-'A'])id[s[i]-'A']=1,tr[++tot]=s[i]-'A';//如果出现了没有遇到的就记录
    int ls=s[0]-'A';//第一个字符一定会是字母
    for(int i=1;i<s.size();i++)
     if(s[i]==':'){//如果是“:”,之后的就是v
      ++i;
      while(i<s.size()&&s[i]!=';')v[ls][s[i]-'A']=v[s[i]-'A'][ls]=1,++i;//一直读到;
     }
     else if(s[i]!=';')ls=s[i]-'A';//再找到下一次的u
}

(2)搜索

//Coder-cjh
bool cmp(int a[],int ans[]){//因为有点怂,所以手写cmp函数
    for(int i=1;i<=tot;i++)
     if(a[i]!=ans[i])
      return a[i]>ans[i];
    return false;
}
void dfs(int step,int md){
    if(md>mind)return;//最优性剪枝
    if(step==tot+1){
     if(md==mind&&cmp(a,ans))return;
     mind=md,memcpy(ans,a,sizeof(a));
     return;
    }
    for(int i=1;i<=tot;i++)
     if(!can[tr[i]]){
         can[tr[i]]=1;//打上标记
         a[step]=tr[i];
         int tmp=0;
         for(int j=1;j<step;j++)
          if(v[tr[i]][a[j]])tmp=max(tmp,step-j);//计算出目前的带宽
         dfs(step+1,max(tmp,md));
         can[tr[i]]=0;
     }
}

猜你喜欢

转载自www.cnblogs.com/coder-cjh/p/11517288.html