广搜的优化

其实主要的思想与深搜类似

放两个题吧

1448:【例题1】电路维修

这个题思想很好(一开始我都不知道qwq)

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int N=300000;
int t,r,c,n;
int dis[N],p[N],cnt;
bool vis[N];
char a[N];
struct node{
       int num,dis;
       bool operator < (node x) const
       {return dis>x.dis;}
}cur;
priority_queue<node>q;
struct edge{int to,nex,val;}e[N<<2];
inline void add(int u,int v,int w)
{
    e[++cnt]=(edge){v,p[u],w};
    p[u]=cnt;
}
inline void dijk()
{
    memset(dis,0x3f,sizeof(dis));dis[1]=0;    
    while(!q.empty())q.pop();
    q.push((node){1,0});
    while(!q.empty())
    {
      cur=q.top();q.pop();
      if(cur.dis!=dis[cur.num])continue;
      int u=cur.num;        
      for(int k=p[u];k;k=e[k].nex)
      {
        int v=e[k].to;
        if(cur.dis+e[k].val<dis[v]){
            dis[v]=cur.dis+e[k].val;
            q.push((node){v,dis[v]});
        } 
      }
      if(dis[n]==0)break;
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(p,0,sizeof(p));cnt=0;
        scanf("%d%d",&r,&c);
        bool flag=0;
        if( (r&1) ^ (c&1) )flag=1;
        for(int i=1;i<=r;++i)
        {
            scanf("%s",a);cin.get();
            if(flag)continue;
            for(int j=1;j<=c;++j)
            {
                char ch=a[j-1];
                int pos1=i*(c+1)+j,pos2=(i-1)*(c+1)+j;                
                if(ch=='/'){
                 add(pos1,pos2+1,0);add(pos2+1,pos1,0);
                  add(pos2,pos1+1,1);add(pos1+1,pos2,1);
                }
                else{
                 add(pos1,pos2+1,1);add(pos2+1,pos1,1);
                  add(pos2,pos1+1,0);add(pos1+1,pos2,0);
                }
            }
        }
        if(flag){cout<<"NO SOLUTION"<<endl;continue;}
        n=(r+1)*(c+1);
        dijk();
        cout<<dis[n]<<endl;
    }
    return 0;
}

1449:【例题2】魔板

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std;
bool bb[9],b[50000];//判重数组 
int MS[9];//我们需要转换到的魔板状态 
char re[10];//用于输出 
struct node{    //每个结点表示该魔板的状态 
    int a[9];    //魔板上的数字 
    int step,father;//已变换步数和其前驱 
    char c;//上一步做的转换 
}l[50000];//总共只有40000多种排列,所以队列不必开很大 

void print(node x){
    int s=0;
    while(x.father!=0){
        re[++s]=x.c;
        x=l[x.father];
    }
    for(int i=s;i>=1;i--){
        printf("%c",re[i]);
    }
    return;
}//通过反复调用目标节点的前驱进行回溯输出 

int fc(int x){        //阶乘 
    if(x==0)return 0;
    if(x==1)return 1;
    return x*fc(x-1);
}
inline int KT(node x){        //康拓展开在这里 
    int num=0;
    for(int i=1;i<=8;i++){
        int s=0;
        for(int j=i+1;j<=8;j++){
            if(x.a[i]>x.a[j])s++;
        }
        num+=s*fc(8-i);
    }
    return num;
}
inline void swapp(int &a,int &b) 
{int c=a;a=b;b=c;}
node A(node),B(node),C(node);

int main(){
    for(int i=1;i<=8;i++)scanf("%d",&MS[i]);
    int head=0,tail=1;
    for(int i=1;i<=9;i++)l[1].a[i-1]=i-1;
    l[1].step=0;
    l[1].father=0;//初始化 
    do
    {
        head++;
        int flag=1;
        for(int i=1;i<=8;i++){
            if(l[head].a[i]!=MS[i]){
                flag=0;break;
            }
        }
        if(flag){
            printf("%d\n",l[head].step);
            print(l[head]);
            return 0;
        }

        for(int i=1;i<=3;i++){
            node k;
            if(i==1)k=A(l[head]);
            if(i==2)k=B(l[head]);
            if(i==3)k=C(l[head]);
            int kk=KT(k);
            if(!b[kk]){
                b[kk]=1;
                tail++;
                l[tail]=k;
                l[tail].step++;
                l[tail].father=head;//记录该状态的前驱(前一步) 
                l[tail].c=i+'A'-1;
            }
        }
    }while(head<tail);//bfs的板子 
    printf("0");
    return 0;
}
node A(node x){
    for(int i=1;i<=4;i++)
        swapp(x.a[i],x.a[9-i]);
    return x;
}
node B(node x){
    for(int i=4;i>=2;i--){
        swapp(x.a[i-1],x.a[i]);
        swapp(x.a[9-i],x.a[10-i]);
    }
    return x;
}
node C(node x){
    swapp(x.a[3],x.a[2]);
    swapp(x.a[7],x.a[6]);
    swapp(x.a[2],x.a[6]);
    return x;//题目所说三种变换 
}

猜你喜欢

转载自www.cnblogs.com/gongcheng456/p/10992798.html