POJ 1753 Flip Game(bfs枚举+递推)

题目地址:http://poj.org/problem?id=1753

这题此前曾经做过,但当时是用的纯BFS做的,然后后来又做了一次组队赛,那是16*16的,果断超时超内存。。能超的都超了。。于是又找了个更好的方法,就是枚举第一行,然后后面的根据第一行的情况推下去。比如,你要让所有的都变成W,如果上一行的对应位置是B的话,那它就必须要翻转。这样能保证前三行的都是W,然后只需判断最后一行就可以判断是不是全翻成了W。代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include<algorithm>

using namespace std;
int mp[20], min1, ff=0;
struct node
{
    int a[20], x, ans;
};
void bfs()
{
    int i, j;
    min1=1000000;
    queue<node>q;
    node f1, f2;
    for(i=0; i<16; i++)
    {
        f1.a[i]=mp[i];
    }
    f1.x=0;
    f1.ans=0;
    q.push(f1);
    while(!q.empty())
    {
        f1=q.front();
        q.pop();
        if(f1.x==4)
        {
            int ans1=0, ans2=0, flag=0;
            for(i=0; i<16; i++)
            {
                f2.a[i]=f1.a[i];
            }
            f2.ans=f1.ans;
            for(i=4; i<16; i++)
            {
                if(f2.a[i-4]==0)
                {
                    f2.a[i-4]=1-f2.a[i-4];
                    f2.a[i]=1-f2.a[i];
                    if(i%4>0)
                        f2.a[i-1]=1-f2.a[i-1];
                    if(i%4<3)
                        f2.a[i+1]=1-f2.a[i+1];
                    if(i+4<16)
                        f2.a[i+4]=1-f2.a[i+4];
                    ans1++;
                }
            }
            for(i=12; i<16; i++)
            {
                if(f2.a[i]==0)
                {
                    flag=1;
                    break;
                }
            }
            if(flag==0)
            {
                if(min1>f2.ans+ans1)
                    min1=f2.ans+ans1;
                ff=1;
            }
            for(i=0; i<16; i++)
            {
                f2.a[i]=f1.a[i];
            }
            f2.ans=f1.ans;
            flag = 0;
            for(i=4; i<16; i++)
            {
                if(f2.a[i-4]==1)
                {
                    f2.a[i-4]=1-f2.a[i-4];
                    f2.a[i]=1-f2.a[i];
                    if(i%4>0)
                        f2.a[i-1]=1-f2.a[i-1];
                    if(i%4<3)
                        f2.a[i+1]=1-f2.a[i+1];
                    if(i+4<16)
                        f2.a[i+4]=1-f2.a[i+4];
                    ans2++;
                }
            }
            for(i=12; i<16; i++)
            {
                if(f2.a[i]==1)
                {
                    flag=1;
                    break;
                }
            }
            if(flag==0)
            {
                if(min1>f2.ans+ans2)
                    min1=f2.ans+ans2;
                ff=1;
            }
            continue ;
        }
        for(i=0; i<16; i++)
        {
            f2.a[i]=f1.a[i];
        }
        f2.x=f1.x+1;
        f2.ans=f1.ans;
        q.push(f2);
        f2.a[f1.x]=1-f1.a[f1.x];
        if(f1.x>=1)
        {
            f2.a[f1.x-1]=1-f1.a[f1.x-1];
        }
        if(f1.x<3)
        {
            f2.a[f1.x+1]=1-f1.a[f1.x+1];
        }
        f2.a[f1.x+4]=1-f1.a[f1.x+4];
        f2.ans=f1.ans+1;
        q.push(f2);
    }
}
int main()
{
    char s[10];
    int i, j;
    for(i=0; i<4; i++)
    {
        scanf("%s",s);
        for(j=0; j<4; j++)
        {
            if(s[j]=='w')
                mp[4*i+j]=1;
            else
                mp[4*i+j]=0;
        }
    }
    bfs();
    if(ff)
        printf("%d\n",min1);
    else
        printf("Impossible\n");
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值