费解的开关

题目链接

这里给出DFS和BFS代码,方便以后回忆。

DFS:

#include <bits/stdc++.h>
 
using namespace std;
int G[30][30],d[5]={0,0,1,0,-1},ans;
 
void Rever(int r,int c)//翻转
{
    for(int i=0;i<5;i++)
        G[r+d[i]][c+d[(i+1)%5]]^=1;
}
 
void resdfs(int r,int c,int cnt)//从第二行翻转,使得上一行全为1
{
   if(cnt>6)
        return;
   else if(r==6)
   {
       for(int i=1;i<=5;i++)
        if(!G[5][i])
        return;
       ans=min(ans,cnt);
       return;
   }
    if(c==6)
    {
        resdfs(r+1,1,cnt);
        return;
    }
    if(!G[r-1][c])
    {
        Rever(r,c);
        resdfs(r,c+1,cnt+1);
        Rever(r,c);
    }
    else
        resdfs(r,c+1,cnt);
}
 
void dfs(int c,int cnt)//枚举第一行所有的翻转可能
{
    if(c>5)
        return;
    Rever(1,c);
    dfs(c+1,cnt+1);
    resdfs(2,1,cnt+1);
    Rever(1,c);
    dfs(c+1,cnt);
    resdfs(2,1,cnt);
}
 
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        for(int i=1;i<=5;i++)
            for(int j=1;j<=5;j++)
               scanf("%1d",&G[i][j]);
    ans=7;
    dfs(1,0);
    if(ans>6)
        ans=-1;
    cout<<ans<<endl;
    }
    return 0;
}

 

BFS:

BFS是从全为1的状态,搜索6步能走到的所有状态。

有一点很奇怪,如果输入为 

printf("%d\n",mp[res]==0?-1:mp[res]);

则会超时。

改成

printf("%d\n",mp[res]-1);

便通过了,运行时间在500ms左右。

#include <bits/stdc++.h>

using namespace std;
map<int,int> mp;

int Rever(int x,int n)
{
    x^=1<<n;
    if(n-1>=0&&n%5) x^=1<<(n-1);
    if(n+1<25&&n%5!=4) x^=1<<(n+1);
    if(n-5>=0) x^=1<<(n-5);
    if(n+5<25) x^=1<<(n+5);
    return x;
}
void bfs()
{
    queue<int>que;
    que.push((1<<25)-1);
    mp[(1<<25)-1]=1;
    while(!que.empty())
    {
        int x=que.front();
        que.pop();
        if(mp[x]>6)
            return;
        for(int i=0;i<25;i++)
        {
            int rex=Rever(x,i);
            if(!mp[rex])
            {
                que.push(rex);
                mp[rex]=mp[x]+1;
            }
        }
    }
}
int main()
{
    bfs();
    int n,x;
    scanf("%d",&n);
    while(n--)
    {
        int res=0;
        for(int i=0;i<5;i++)
            for(int j=0;j<5;j++)
        {
            scanf("%1d",&x);
            res=(res<<1)+x;
        }
        printf("%d\n",mp[res]-1);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值