zoukankan      html  css  js  c++  java
  • 广搜的优化

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

    放两个题吧

    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
    ",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;//题目所说三种变换 
    }
  • 相关阅读:
    自定义配置文件的使用
    网络编程入门建议
    SQL2005 表分区亲测
    数据库文件组小记
    eclipse 项目显示红叉
    Flex DataGrid可编辑对象实现Enter跳转
    excel 巧用功能
    ACCESS中查询语句:查询所得数据另存到一个指定目录下的文件夹里,并新建新的文件
    邮件合并 :处理ACCESS中批量查询语句的运行
    文件分类批处理程序
  • 原文地址:https://www.cnblogs.com/gongcheng456/p/10992798.html
Copyright © 2011-2022 走看看