搜索算法_PROBLEM

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

魔法数字

这里写图片描述
(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)
这里写图片描述
时间限制: 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

这里写图片描述
这里写图片描述
只有一组测试数据,保证 T<= 10且 n=12的数据不超过 2组, n=11的数据不的数据不的数据不超过2组

题解

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

没有code

MARK一下MARIX—TREE

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值