较复杂搜索,剪枝

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\n",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\n",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

 

posted @ 2017-08-21 17:50  安月冷  阅读(198)  评论(0编辑  收藏  举报