zoukankan      html  css  js  c++  java
  • 较复杂搜索,剪枝

    1.hdu1429

    思路:

    把这10把钥匙当成每一个为,要要1<<10个位保存所有的状态,
    然后就是模拟捡起钥匙,捡起钥匙就是说明这个位上的数字变成1这个状态,
    只要|一下就好了,然后改变在这个点的状态。。。。模拟碰到门的情况,
    那么就和这个位置上的位&一次,看是1还是0,1代表已经捡到了这把钥匙,可以开门

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    
    #define N 30
    
    using namespace std;
    char map[N][N],str[N];;
    int n,m,t;
    bool vis[N][N][(1<<11)];
    int dx[]= {-1,1,0,0};
    int dy[]= {0,0,-1,1};
    struct node
    {
        int x,y,step,key;
    }st;
    queue<node>Q;
    
    bool check(int x,int y)
    {
        if(x>=1&&x<=n&&y>=1&&y<=m&&map[x][y]!='*') return true;
        return false;
    }
    
    int bfs()
    {
        while(!Q.empty())  Q.pop();
        memset(vis,false,sizeof(vis));
        vis[st.x][st.y][st.key]=true;
        st.key=st.step=0;Q.push(st);
        node cur,nex;
        while(!Q.empty())
        {
            cur=Q.front();Q.pop();
            if(map[cur.x][cur.y]=='^')return cur.step;
            for(int i=0; i<4; i++)
            {
                nex.x=cur.x+dx[i];nex.y=cur.y+dy[i];
                nex.key=cur.key;
                if(!check(nex.x,nex.y)) continue;
                nex.step=cur.step+1;
                if(nex.step>=t) continue;
                else if(map[nex.x][nex.y]>='A' && map[nex.x][nex.y]<='Z')
                {
                    int temp=map[nex.x][nex.y]-'A';
                    int K=cur.key&1<<temp;
                    if(K && !vis[nex.x][nex.y][nex.key])
                    {
                        vis[nex.x][nex.y][nex.key]=true;
                        Q.push(nex);
                    }
                }
                else if(map[nex.x][nex.y]>='a' && map[nex.x][nex.y]<='z')
                {
                    int temp=map[nex.x][nex.y]-'a';
                    nex.key=cur.key|1<<temp;
                    if(!vis[nex.x][nex.y][nex.key])
                    {
                        vis[nex.x][nex.y][nex.key]=true;
                        Q.push(nex);
                    }
                }
                else
                {
                    if(!vis[nex.x][nex.y][nex.key])
                    {
                        vis[nex.x][nex.y][nex.key]=true;
                        Q.push(nex);
                    }
                }
            }
        }return -1;
    }
    
    inline void init()
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str+1);
            for(int j=1;j<=m;j++)
            {
                if(str[j]=='@')
                {
                    st.x=i;st.y=j;
                    map[i][j]=str[j];
                }
                else  map[i][j]=str[j];
            }
        }
    }
    
    int main()
    {
        while(~scanf("%d%d%d",&n,&m,&t))
        {
            init();
            int ans=bfs();
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

     2.洛谷1731

    思路:

    ①要是剩下体积除以最大(虽然取不到)半径所得到的表面积+累计表面积大于答案退出
    ② 要是剩下来的体积已经小于该层最小体积了就退出
    ③ 还有 为了剪枝,我们要起先预处理某一层的最大不可的表面积和体积

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    
    #define maxn 17
    
    using namespace std;
    int NN,M,N,ans;
    int ss[maxn],sv[maxn];
    
    void dfs(int t,int S,int V,int lR,int lH)//层数,已用总面积,已用总体积,上一层半径 ,上一层高度
    {
        if (t==0)
        {
            if (V==N) ans=min(ans,S);
            return ;
        }
        if (V+sv[t]>N) return;
        if (S+ss[t]>ans) return;
        if (S+2*(N-V)/lR>ans) return;
        for (int r=lR-1;r>=t;r--)
        {
            if (t==M) S=r*r;
            int maxh=min((N-V-sv[t-1])/(r*r),lH-1);
            for (int h=maxh;h>=t;h--)
              dfs(t-1,S+2*r*h,V+r*r*h,r,h);
        }
    }
    
    int main()
    {
        scanf("%d%d",&N,&M);
        for (int i=1;i<=M;i++)
        {
            ss[i]=2*i*i;ss[i]+=ss[i-1];
            sv[i]=i*i*i;sv[i]+=sv[i-1];
        }ans=0x3f3f3f3f;
        dfs(M,0,0,sqrt(N),N);
        if (ans==0x3f3f3f3f) printf("0");
        else printf("%d
    ",ans);
        return 0;
    }
    View Code

    3.虫食算

    思路:

    嗯...倒着搜,一列一列的搜
    边搜边剪枝。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    
    #define N 27
    
    using namespace std;
    int n,m,ans,cnt,tmp;
    char s1[N],s2[N],s3[N];
    int match[N];
    bool vis[N];
    
    void dfs(int use,bool flag=false)
    {
        if(use==n)
        {
            if(!flag)
            {
                for(int i=0;i<n;i++) printf("%d ",match[i]);
                exit(0);
            }
            else return;
        }
        
        for(int k=n-2-use;k>=0;k--)
          if(match[s1[k]]!=-1 && match[s2[k]]!=-1 && match[s3[k]]!=-1 
            && (match[s1[k]]+match[s2[k]])%n!=match[s3[k]] 
            && (1+match[s1[k]]+match[s2[k]])%n!=match[s3[k]]) return;
        
        int tmp=n-1-use;
        if(match[s1[tmp]]==-1)
        {
            for(int k=n-1;k>=0;k--)
            {
                if(!vis[k])
                {
                    vis[k]=1;match[s1[tmp]]=k;
                    dfs(use,flag);
                    vis[k]=0;match[s1[tmp]]=-1;
                }
            }
        }   
        else if(match[s2[tmp]]==-1)
        {
            for(int k=n-1;k>=0;k--)
            {
                if(!vis[k])
                {
                    vis[k]=1;match[s2[tmp]]=k;
                    dfs(use,flag);
                    vis[k]=0;match[s2[tmp]]=-1;
                }
            }
        }
        else if(match[s3[tmp]]==-1)
        {
            int pre=match[s1[tmp]]+match[s2[tmp]]+flag;
            for(int k=0;k<n;k++)
              if(match[k]==pre%n) return;
            match[s3[tmp]]=pre%n;
            vis[match[s3[tmp]]]=1;
            dfs(use+1,pre>=n);
            vis[match[s3[tmp]]]=0;
            match[s3[tmp]]=-1;
        }
        else
        {
            int pre=match[s1[tmp]]+match[s2[tmp]]+flag;
            if(match[s3[tmp]]==pre%n) dfs(use+1,pre>=n);
        }
        
    }
    
    int main()
    {
        scanf("%d%s%s%s",&n,s1,s2,s3);
        for(int i=0;i<n;i++)
        {
            match[i]=-1;
            s1[i]-='A';s2[i]-='A';s3[i]-='A';
        }dfs(0);
        return 0;
    }
    View Code
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    python3 进程_multiprocessing模块
    python3 线程_threading模块
    python3 异常处理
    python3 面向对象补充
    python3 多态,绑定方法与非绑定方法
    python3 uper(),继承实现原理,封装
    python3 面向对象、类、继承、组合、派生、接口、子类重用父类方法
    python3 正则表达式re模块
    python3 json、logging、sys模块
    mysql查询练习
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7405823.html
Copyright © 2011-2022 走看看