欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

搜索算法_PROBLEM

程序员文章站 2022-06-03 23:40:22
...

今天胡老说考搜索就是考暴力,没有分的就不用来了,结果最后。。。
我是唯一有分的,GG。
第三道题太难了,我就不写了。。。

魔法数字

搜索算法_PROBLEM
(A.pas/.c/.cpp)
时间限制:1.0s,空间限制131072 KB
题目描述:
给一个六位数A 和另外一个六位数B.
你有一根魔法棒,初始时指向A 的最左边数字,每一次你可以选择下列操作
之一:
1.将当前魔杖指向的数字与最左端的一个数字调换位置。
2.将当前魔杖指向的数字与最右端的一个数字调换位置。
3.将当前魔杖指向的数字+1。(若当前魔杖指向的数字为9 则无效)
4.将当前魔杖指向的数字−1。(若当前魔杖指向的数字为0 则无效)
5.将当前魔杖向右移动一位。
6.将当前魔杖向左移动一位。
输入描述:
多组数据,处理到EOF
对于每组数据,包含两个6 位数A,B
输出描述:
对于每组数据,输出一行表示答案..

样例输入:
1
123456 654321
样例输出:
11

数据范围:
100%的数据保证:1 <= 数据组数 <= 200

题解

直接暴力搜索所有数字?不可行
只需要考虑这些数字在哪些位置是否出现过,6^6状态

code

#include<cstdio>
#include<cstring>
const int maxn=1000005;
const int HASH=1428571;
struct data{
    int k,v;
    bool a[6];
}q[maxn];
int vis[HASH+1],v[maxn],tennum[8]={1000000},sum[8],num[8],a,b,head,tail,LM;
bool judge(int u){
    int h=q[u].v%HASH,t=vis[h];
    while(t!=-1){
        if(q[u].v==q[t].v)return 0;
        t=v[t];
    }
    v[u]=vis[h],vis[h]=u;   
    return 1;
}
void FH(data u,int k){
    q[tail].k=u.k+1,q[tail++].a[k]=1;
}
void FS(int f,int k,int id,data u){
    if(f){
        q[tail]=u;
        int t=num[k],v=0;num[k]=num[id],num[id]=t;
        for(register int i=0;i<=6;++i)v+=num[i]*tennum[i];
        q[tail].v=v;
        if(judge(tail))FH(u,k);
        num[id]=num[k],num[k]=t;
    }
}
void FT(int f,data p,int u){
    q[tail]=p;
    int v=LM+f;
    q[tail].v=v;
    if(judge(tail))FH(p,u+f);
}
int bfs(){
    head=0,tail=1;
    judge(head);
    while(head<tail){
        data p=q[head++];
        LM=p.v;
        for(register int i=6;i>=0;--i)num[i]=p.v%10,p.v/=10;
        int u=num[6],f;
        f=1;
        if((!num[u])||(!u))f=0;
        FS(f,0,u,p);
        f=1;
        if(((!num[5])&&(!u))||u==5)f=0;
        FS(f,5,u,p);
        if(u<5)FT(1,p,u);
        if(u) FT(-1,p,u);
    }
    return tail;
}
int main(){
    freopen("A.in","r",stdin);
    freopen("A.out","w",stdout);
    for(register int i=1;i<=6;++i)
        tennum[i]=tennum[i-1]/10;
    while(scanf("%d%d",&a,&b)!=EOF){
        memset(vis,-1,sizeof(vis));
        memset(q[0].a,0,sizeof(q[0].a));
        q[0].v=a*10,q[0].k=0,q[0].a[0]=1;
        for(register int i=5;i>=0;--i)sum[i]=b%10,b/=10;
        int res=bfs(),ans=999999;
        for(register int i=0;i<res;++i){
            q[i].v/=10;
            int num[6],rez=q[i].k;
            for(register int j=5;j>=0;--j){
                num[j]=q[i].v%10;
                q[i].v/=10;
            }
            for(register int k=0;k<6;++k)
                if(sum[k]!=num[k]&&!q[i].a[k]){
                    rez=999999;break;
                }else rez+=((sum[k]-num[k])>0?(sum[k]-num[k]):-(sum[k]-num[k]));
            ans=ans>rez?rez:ans;
        }
        printf("%d\n",ans);
    }
    return 0;   
}

BitMask

(B.pas/.c/.cpp)
搜索算法_PROBLEM
时间限制: 3.0s,空间限制 131072 KB
题目描述:
给出 2 x n的方格,每个方格初始都没有颜色,每次你可以选择其中一矩形区域,将其涂成某个颜色 C,现给出最终状态,请问少需要多步能到达 最终状态?
输入描述:
输入第一行为一个整数T,表示数据组数
对于每组数据输入的第一行表示n( 1 <= n <= 8 ),接下来 2行,每个一长度n的字符串,保证字符串只包含大写字母
输出描述:
对于每组数据,输出一行表示答案 对于每组数据,输出一行表示答案 对于每组数据,输出一行表示答案 对于每组数据,输出一行表示答案 对于每组数据,输出一行表示答案 对于每组数据,输出一行表示答案 对于每组数据,输出一行表示答案 。
样例输入:
3
3
ABA
CBC
3
BAA
CCB
3
BBB
BAB
样例输出:
3
3
2
数据范围:
50%的数据保证: 1 <= T <= 200且 n是随机产生的 是随机产生的
50%的数据保证: 1 <= T <= 25 且 n 为 8

题解

直接暴力BFS即可,每次抽取一个矩形进行位运算即可

code

#include<cstdio>
#include<cstring>
#define rep(i,x,y) for(register int i=x;i<y;++i)
#define CM(x,v) memset((x),v,sizeof(x))
char mp[3][10];
bool vis[27];
int t,n,m,head,tail,tot,u,v,dis[1<<17],Q[1<<19]; 
void bfs(int x){
    CM(dis,-1);
    head=tail=dis[x]=0;
    Q[tail++]=x;
    while(head!=tail){
        u=Q[head++];
        rep(F1,0,n)rep(F2,F1,n)rep(F3,0,2)rep(F4,F3,2){
            CM(vis,0),tot=0;
            rep(i,F3,F4+1)rep(j,F1,F2+1){
                if(tot>1)break;
                if((u&(1<<(i*n+j))))continue;
                if(!vis[mp[i][j]-'A'])++tot,vis[mp[i][j]-'A']=1;
            }
            if(tot==1){
                v=u;
                rep(i,F3,F4+1)rep(j,F1,F2+1)v|=1<<(i*n+j);
                if(dis[v]==-1){
                    dis[v]=dis[u]+1;
                    if(v==m)return;
                    if(dis[v]<(n<<1))Q[tail++]=v;
                }
            }
        }
    }
}
template<class T>inline void readin(T &res){
    static char ch;T flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
inline void readst(char x[]){
    static char ch;int len=0;
    while((ch=getchar())<'A'||ch>'Z');x[len++]=ch;
    while((ch=getchar())>='A'&&ch<='Z')x[len++]=ch;
}
int main(){
    freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);
    readin(t);
    while(t--){
        readin(n),readst(mp[0]),readst(mp[1]);
        m=(1<<(n<<1))-1,bfs(0);
        printf("%d\n",dis[m]);
    }
    return 0;
}

BruteForce

搜索算法_PROBLEM
搜索算法_PROBLEM
只有一组测试数据,保证 T<= 10且 n=12的数据不超过 2组, n=11的数据不的数据不的数据不超过2组

题解

首先暴力的求出环的方案数
之后暴力枚举环之后缩点用Matrix-Tree定理计算生成树即可

没有code

MARK一下MARIX—TREE