【HDOJ】2209 翻纸牌游戏

状态压缩+双向广搜。注意控制时间t。

/* 2209 */
#include <iostream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000")

#define sti                set<int>
#define stpii            set<pair<int, int> >
#define mpii            map<int,int>
#define vi                vector<int>
#define pii                pair<int,int>
#define vpii            vector<pair<int,int> >
#define rep(i, a, n)     for (int i=a;i<n;++i)
#define per(i, a, n)     for (int i=n-1;i>=a;--i)
#define clr                clear
#define pb                 push_back
#define mp                 make_pair
#define fir                first
#define sec                second
#define all(x)             (x).begin(),(x).end()
#define SZ(x)             ((int)(x).size())
#define lson            l, mid, rt<<1
#define rson            mid+1, r, rt<<1|1

const int maxn = 1<<20;
bool mark1[maxn+5];
bool mark2[maxn+5];
char s[25];
int m[25];

void init() {
    m[0] = 1;
    rep(i, 1, 25)
        m[i] = m[i-1]<<1;
}

void bfs() {
    queue<int> Q1, Q2;
    int x = 0, xx;
    int i, j, k;
    int t = 0;

    memset(mark1, false, sizeof(mark1));
    memset(mark2, false, sizeof(mark2));

    for (i=0; s[i]; ++i)
        x = (x<<1) + s[i]-‘0‘;

    if (x == 0) {
        puts("0");
        return ;
    }

    int l = i;
    Q1.push(x);
    mark1[x] = true;
    Q2.push(0);
    mark2[0] = true;
    int sz1, sz2;

    while (!Q1.empty() && !Q2.empty()) {
        ++t;

        sz1 = SZ(Q1);
        while (sz1--) {
            x = Q1.front();
            Q1.pop();
            for (i=0; i<l; ++i) {
                xx = x;
                xx ^= m[i];
                if (i)
                    xx ^= m[i-1];
                if (i+1 < l)
                    xx ^= m[i+1];
                if (mark1[xx])
                    continue;
                if (mark2[xx]) {
                    printf("%d\n", t+t-1);
                    return ;
                }
                mark1[xx] = true;
                Q1.push(xx);
            }
        }

        sz2 = SZ(Q2);
        while (sz2--) {
            x = Q2.front();
            Q2.pop();
            for (i=0; i<l; ++i) {
                xx = x;
                xx ^= m[i];
                if (i)
                    xx ^= m[i-1];
                if (i+1 < l)
                    xx ^= m[i+1];
                if (mark2[xx])
                    continue;
                if (mark1[xx]) {
                    printf("%d\n", t+t);
                    return ;
                }
                mark2[xx] = true;
                Q2.push(xx);
            }
        }
    }

    puts("NO");
}

int main() {
    ios::sync_with_stdio(false);
    #ifndef ONLINE_JUDGE
        freopen("data.in", "r", stdin);
        freopen("data.out", "w", stdout);
    #endif

    init();
    while (scanf("%s", s)!=EOF) {
        bfs();
    }

    #ifndef ONLINE_JUDGE
        printf("time = %d.\n", (int)clock());
    #endif

    return 0;
}
时间: 2024-10-10 15:21:12

【HDOJ】2209 翻纸牌游戏的相关文章

HDU 2209 翻纸牌游戏(dfs)

翻纸牌游戏 Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2180    Accepted Submission(s): 787 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张

hdu 2209 翻纸牌游戏

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2209 这个题难度还可以 我的思路:有n张牌成第一张牌开始如果是1,则第一张第二张第三张翻转,再看第二张,判断如果是1则第二张第三张第四张翻转,以此下去 不这样还不可以,还得分两种情况如001 按这种思路是不可以的所以还有一种情况不管如何先翻转第一和第二张牌再如上一种思路. 我的AC代码 第一种写法:直接法 #include<cstdio>#include<iostream>#inclu

HDU 2209 翻纸牌游戏(DFS)

题目链接 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作. Input 有多个case,每个case输入一行01符号串(长度不超过2

hdu2209翻纸牌游戏(bfs+状态压缩)

Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作. Input 有多个case,每个case输入一行01符号串(长度不超过20),1表

翻纸牌游戏(dfs回溯)

翻纸牌游戏 Time Limit : 9000/3000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 2   Accepted Submission(s) : 2 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张纸牌(由正翻

HDU2209 ( 翻纸牌游戏 )

思路:枚举然后深搜,时间复杂度有点高. 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 int a[25]; 7 char c[25]; 8 int flag; 9 int len; 10 int judge() 11 { 12 int i,j; 13 int cnt=0; 14 for

HDU2209 翻纸牌游戏【技巧】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2209 题目大意: 有N张牌,有正面朝上的,也有反面朝上的,现在需要把所有牌都正面朝上,已知每翻一张纸牌, 该纸牌左右两侧各一张纸牌也跟着翻动.现在给你一行只包含字符'0'和'1'的01字符串,'1'代表纸牌 反面,'0'代表纸牌正面.现在需要将字符串变为全为"0000-00"的字符串,一次操作只能改变一个 字符本身和它左右两侧各一个字符,问:最少要经过多少次操作,才能使字符串变为&quo

HDOJ 2209 贪心

翻纸牌游戏 Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3669    Accepted Submission(s): 1371 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一

HDOj-2209-翻纸牌游戏-DFS

翻纸牌游戏 Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2622    Accepted Submission(s): 943 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一