现在的位置: 首页 > 综合 > 正文

hdu 2209 翻纸牌游戏 (状态bfs解)

2017年10月18日 ⁄ 综合 ⁄ 共 1061字 ⁄ 字号 评论关闭

小记:A了这题又长了记性了。定了个全局变量又定了一个相同变量名的局部变量,一直测试不对,想法是肯定是对的。最后想了好久,终于看到了,唉,,b了。

题解:这题,因为只有0和1两种状态,而且题目也说了只有不超过20位的长度,因此我们可以将这个串转换成一个整数值,而每种翻转而成的状态都是唯一的,因此这个值也是唯一的,这个就很好的解决了搜索中某个状态是否搜索过的问题了。不过也是利用空间换时间,看题目提交的情况,唉,大神们就是大神们,差距太大了。如果有看到本文的,有更好的解决方案的大神,给小弟支个招,教教咱。在此先谢过。 继续,有了保存状态的方法后,就直接对每一种状态中的每一位进行bfs,当状态值为0时即表示已搜到,就返回。记得对每一个状态进行标记是否已搜索。

代码奉上:

#include <stdio.h>
#include <string.h>
#include <queue>

using namespace std;
#define MAX 1<<20
#define N 50

char s1[N];
int visited[MAX],num[MAX];
int len;

int bfs(int x){
    queue<int>q;
    q.push(x);
    int i, now, next;
    while(!q.empty()){
        now = q.front();//取头
        q.pop();//头出队
        for (i = 1; i <= len; i++){
            if(i == 1)
                next = now^3;//最左翻转两个
            else
                next = now^(7<<(i-2));//中间翻转3个

            next &= (1<<len)-1;//最右的时候翻转了三个,消掉一个

            if(visited[next])continue;//是否已搜过

            visited[next] = 1;//标记为已搜
            num[next] = num[now] + 1;//最少次数加一
            if(next == 0)   return num[next];//是否搜到了
            q.push(next);//没有,则入队
        }
    }
    return -1;
}

int main()
{
    int i, a;
    while(scanf("%s",s1)!=EOF){
        len = strlen(s1);
        a = 0;
        for(i = 0;i < len;i++)
            a = (a<<1) + s1[i] -'0';
        if(a){
            memset(visited,0,sizeof(visited));
            memset(num,0,sizeof(num));
            a = bfs(a);
        }
        if(a == -1)
            printf("NO\n");
        else printf("%d\n",a);
    }
    return 0;
}

抱歉!评论已关闭.