1016. Boundaries on A New Kind of Science 解题报告

题目链接:

http://soj.sysu.edu.cn/1016

题目大意:

给定一个字符串和256条规则,将某条规则应用于字符串,字符串将发生变化,给定一个数max,求出在max步内可以将字符串变为指定字符串的规则号以及步数。

题目分析:
既然只有256条规则,而且步数又有限制,那我们就暴力模拟,把所有情况都求出来就行了,但是如果用原始字符串来做是非常慢的,虽然题目的时间限制很宽松(10s),但也是会超时的。所以对于每个规则我用一个record的map来保存已经遇到过的字符串,这样就可以过了(虽然还是很慢)。

在网上看到的做法是用0,1分别代表白黑的,而且用到了很多位运算,虽然也是暴力,但是快很多,一样的测试,人家0.15s就过了。

代码:

// Problem#: 1016
// Submission#: 3585804
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>
#include <string.h>

//
int rule[256][8], m[15];
long long step, length;
char num[20], target[300];
int targetNum[300], pro[2][300];
int answerNum, ans1[300], ans2[300];

int MAX() {
    if (length < 11) return m[length];
    else return 985;
}

void init() {
    for (int i = 0; i < 256; i++) {
        int temp = i;
        for (int j = 0; j < 8; j++) {
            rule[i][j] = temp & 1;
            temp >>= 1;
        }
    }
    m[0] = 1;
    for (int i = 1; i < 11; i++) m[i] = m[i - 1] << 1;
}

bool check() {
    length = strlen(target);
    if (length < 3) return false;
    for (int i = 0; i < length; i++) {
        if (target[i] == 'W') targetNum[i] = 0;
        else if (target[i] == 'B') targetNum[i] = 1;
        else return false;
    }
    if ((targetNum[0] == 1) || (targetNum[length - 1] == 1) || (length & 1 == 0)) return false;
    return true;
}

int main() {
    init();

    int caseNum = 1;

    while (1) {
        
        scanf("%s%s", num, target);
        
        if (strcmp(num, "END") == 0) break;
        
        printf("LINE %d ", caseNum++);

        if (!check()) {
            printf("NONE\n");
            continue;
        }
        
        step = 0;
        for (int i = 0; num[i] != '\0'; i++) step = step * 10 + num[i] - '0';
        if (step > MAX()) step = MAX();

        answerNum = 0;

        for (int i = 0; i < 256; i++) {
            memset(pro, 0, sizeof(pro));
            int last = 0, now = 1;
            int s = 1;
            int jlength = length - 2, ruleNum;
            pro[now][length / 2] = 1;
            while (1) {
                
                if (s > step) break;

                bool isSame = true;
                for (int k = 0; k < length; k++) {
                    if (pro[now][k] != targetNum[k]) {
                        isSame = false;
                        break;
                    }
                }
                if (isSame) {
                    ans1[answerNum] = i;
                    ans2[answerNum] = s;
                    answerNum++;
                    break;
                }
                now ^= 1;
                last ^= 1;
                
                s++;
                for (int j = 0; j < jlength; j++) {
                    ruleNum = pro[last][j];
                    ruleNum <<= 1;
                    ruleNum += pro[last][j + 1];
                    ruleNum <<= 1;
                    ruleNum += pro[last][j + 2];
                    pro[now][j + 1] = rule[i][ruleNum];
                }
                pro[now][0] = pro[now][length - 1] = 0;
            }
        }
        if (answerNum) {
            for (int i = 0; i < answerNum; i++) printf("(%d,%d)", ans1[i], ans2[i]);
            printf("\n");
        } else printf("NONE\n");
    }
    return 0;
}                                 

 

这提示我以后能用int尽量不用字符串。多考虑效率。这道题要是时间限制到1s我就GG了。

我的代码:

#include <iostream>
#include <map>
#include <vector>
#include <string.h>
using namespace std;

struct Ans {
    int mo, t;
    Ans(){}
    Ans(int a, int b) {
        mo = a;
        t = b;
    }
};
//0 for white, 1 for black
int model[9];
map<string, int> transfer;
map<string, int> record;
vector<Ans> ans;
int Max;
string line;
string ary, dest, ary2;
int l;

void addModel() {
    int i = 8, j;
    while (i >= 0 && model[i]) {
        i--;
    }
    for (j = i; j <= 8; j++) {
        model[j] = 1-model[j];
    }
}

int toInt(string tmp) {
    int i, tot = 0;
    for (i = 0; i < tmp.length(); i++) {
        tot = tot*10 + tmp[i] - '0';
    }
    return tot;
}

void getData(int& n, string& r) {
    string tmp1, tmp2;
    tmp1 = tmp2 = "";
    int i;
    for (i = 0; r[i] != ' '; i++) {
        tmp1 += r[i];
    }
    for (i++; i<r.length(); i++) {
        tmp2 += r[i];
    }
    n = toInt(tmp1);
    dest = tmp2;
    l = dest.length();
}

bool cut(int f) {
    string tmp;
    int i;
    for (i = 0; i < 3; i++) {
        tmp += ary2[f+i];
    }
    return model[transfer[tmp]];
}

void Do() {
    int i;
    ary2 = ary;
    for (i = 0; i < l-2; i++) {
        if (cut(i)) {
            ary[i+1] = 'B';
        } else {
            ary[i+1] = 'W';
        }
    }
}

bool equal(const string& a, const string& b) {
    int i;
    for (i = 0; i < l; i++) {
        if (a[i] != b[i]) {
            return false;
        }
    }
    return true;
}

int main() {
    transfer["BBB"] = 1;
    transfer["BBW"] = 2;
    transfer["BWB"] = 3;
    transfer["BWW"] = 4;
    transfer["WBB"] = 5;
    transfer["WBW"] = 6;
    transfer["WWB"] = 7;
    transfer["WWW"] = 8;
    int cnt = 0;
    while (getline(cin, line)) {
        cnt++;
        if (line == "END OF INPUT")
            break;
        ans.clear();
        getData(Max, line);
        int i, j, k;
        for (i = 0; i < 256; i++) {
            ary = "";
            for (k = 0; k < l; k++) {
                ary += 'W';
            }
            ary[l/2] = 'B';
            record.clear();
            for (j = 0; j < Max; j++) {
                if (record[ary]) {
                    break;
                }
                if (equal(ary, dest)) {
                    ans.push_back(Ans(i, j+1));
                    break;
                } else {
                    record[ary] = 1;
                }
                Do();
            }
            addModel();
        }
        cout << "LINE " << cnt << " ";
        for (i = 0; i < ans.size(); i++) {
            cout << "(" << ans[i].mo << "," << ans[i].t << ")";
        }
        if (!ans.size()) {
            cout << "NONE";
        }
        cout << endl;
    }
}
posted @ 2016-03-01 16:46  IVY_BUG  阅读(192)  评论(0编辑  收藏  举报