长安大学新生赛 H题 拉面女神的魔盒

再简单说明一下题意,规定一开始按钮状态为0 0 0 0 0 0,输入终点状态,求最少的操作步数,对于每个按钮,有以下规定:

按钮①:可以任意想顺时针或者逆时针旋转,一次转动一格

按钮②:当6个旋钮的数字中奇数偶数个数为相同时才能转动,向顺时针或者逆时针转动一格

按钮③:只能向逆时针方向转动,一次转动7格。

按钮④:只能向逆时针方向转动,一次转动(sum % 9 + 1)格,sum为当前六个数之和

按钮⑤:当①③⑤这三个旋钮数字之和正好为9的时候才能转动,顺时针或者逆时针旋转一格

按钮⑥:当按钮②的数字为0的时候才能转动,只能向顺时针转动,一次转动三格。


这个题一开始反应的是能否直接用DFS并判重来做。。然而明显不可以。

后来发现其实这肯定是个BFS的题目,进而根据题目知道终点,知道起点这个特性,想到可以用A*或者双向BFS来做,但是不知道怎么列启发式函数,所以就用双向BFS来做吧。代码很长,因为正向和反向不完全一样的判断条件,比较坑。。。未提交过,可能有错误,欢迎指正。

代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#include <vector>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <queue>
using namespace std;

struct VIS{
    int flag;
    int step;
}vis[1000001];

int dis[2] = {1, -1};

struct num{
    int n[6];
    int step;
    friend bool operator <(num a, num b)
    {
        return a.step < b.step;
    }
};

int ans[6];
int init[6];

bool judge(num a){
    for(int i = 0; i < 6; i ++)
        if(a.n[i] != ans[i]);
            return false;
    return true;
}

int total(num a){
    int i, sum;
    sum = 0;
    for(i = 0; i < 6; i ++)
        sum = sum * 10 + a.n[i];
    return sum;
}

int bfs(void){
    memset(vis, 0, sizeof(vis));
    queue<num> q;
    queue<num> p;
    num pre, lst;
    int i, t,  sp = 0;
    long sum;

    for(i = 0; i < 6; i ++)
        pre.n[i] = init[i];
    sum = total(pre);
    vis[sum].flag = 1;
    vis[sum].step = 0;
    pre.step = 0;
    q.push(pre);

    for(i = 0; i < 6; i ++)
        lst.n[i] = ans[i];
    sum = total(lst);
    vis[sum].flag = 2;
    vis[sum].step = 0;
    lst.step = 0;
    p.push(lst);

    while(!q.empty() && !p.empty()){
        while(q.front().step == sp){
            pre = q.front();
            q.pop();
            for(i = 0; i < 6; i ++){
                if(i == 0){
                    for(t = 0; t < 2; t ++){
                        lst = pre;
                        lst.n[0] = pre.n[0] + dis[t];
                        if(lst.n[i] < 0)
                            lst.n[i] += 10;
                        else if(lst.n[i] >= 10)
                            lst.n[i] -= 10;
                        sum = total(lst);
                        lst.step = pre.step + 1;
                        if(vis[sum].flag == 1)
                            continue;
                        if(vis[sum].flag == 2)
                            return lst.step + vis[sum].step;
                        vis[sum].flag = 1;
                        vis[sum].step = lst.step;
                        q.push(lst);
                    }
                }
                else if(i == 1){
                    int temp = 0;
                    for(int j = 0; j < 6; j ++){
                        if(pre.n[j] % 2)
                            temp ++;
                        else
                            temp --;
                    }
                    if(temp != 0)
                        continue;
                    for(t = 0; t < 2; t ++){
                        lst = pre;
                        lst.n[1] = pre.n[1] + dis[t];
                        if(lst.n[i] < 0)
                            lst.n[i] += 10;
                        else if(lst.n[i] >= 10)
                            lst.n[i] -= 10;
                        sum = total(lst);
                        lst.step = pre.step + 1;
                        if(vis[sum].flag == 1)
                            continue;
                        if(vis[sum].flag == 2)
                            return lst.step + vis[sum].step;
                        vis[sum].flag = 1;
                        vis[sum].step = lst.step;
                        q.push(lst);
                    }
                }
                else if(i == 2){
                    lst = pre;
                    lst.n[2] = pre.n[2] + 7;
                    if(lst.n[i] < 0)
                        lst.n[i] += 10;
                    else if(lst.n[i] >= 10)
                        lst.n[i] -= 10;
                    sum = total(lst);
                    lst. step = pre.step + 1;
                    if(vis[sum].flag == 1)
                        continue;
                    if(vis[sum].flag == 2)
                        return lst.step + vis[sum].step;
                    vis[sum].flag = 1;
                    vis[sum].step = lst.step;
                    q.push(lst);
                }
                else if(i == 3){
                    lst = pre;
                    int temp = 0;
                    for(int j = 0; j < 6; j ++){
                        temp += lst.n[j];
                    }
                    temp = temp % 9 + 1;
                    lst.n[3] = pre.n[3] + temp;
                    if(lst.n[i] < 0)
                        lst.n[i] += 10;
                    else if(lst.n[i] >= 10)
                        lst.n[i] -= 10;
                    sum = total(lst);
                    lst. step = pre.step + 1;
                    if(vis[sum].flag == 1)
                        continue;
                    if(vis[sum].flag == 2)
                        return lst.step + vis[sum].step;
                    vis[sum].flag = 1;
                    vis[sum].step = lst.step;
                    q.push(lst);
                }
                else if(i == 4 && (pre.n[0] + pre.n[2] + pre.n[4] == 9)){
                    for(t = 0; t < 2; t ++){
                        lst = pre;
                        lst.n[4] = pre.n[4] + dis[t];
                        if(lst.n[i] < 0)
                            lst.n[i] += 10;
                        else if(lst.n[i] >= 10)
                            lst.n[i] -= 10;
                        sum = total(lst);
                        lst.step = pre.step + 1;
                        if(vis[sum].flag == 1)
                            continue;
                        if(vis[sum].flag == 2)
                            return lst.step + vis[sum].step;
                        vis[sum].flag = 1;
                        vis[sum].step = lst.step;
                        q.push(lst);
                    }
                }
                else if(i == 5 && pre.n[1] == 0){
                    lst = pre;
                    lst.n[5] = pre.n[5] - 3;
                    if(lst.n[i] < 0)
                        lst.n[i] += 10;
                    else if(lst.n[i] >= 10)
                        lst.n[i] -= 10;
                    sum = total(lst);
                    lst. step = pre.step + 1;
                    if(vis[sum].flag == 1)
                        continue;
                    if(vis[sum].flag == 2)
                        return lst.step + vis[sum].step;
                    vis[sum].flag = 1;
                    vis[sum].step = lst.step;
                    q.push(lst);
                }
            }
        }


        while(p.front().step == sp){
            pre = p.front();
            p.pop();

            for(i = 0; i < 6; i ++){
                if(i == 0){
                    for(t = 0; t < 2; t ++){
                        lst = pre;
                        lst.n[0] = pre.n[0] + dis[t];
                        if(lst.n[i] < 0)
                            lst.n[i] += 10;
                        else if(lst.n[i] >= 10)
                            lst.n[i] -= 10;
                        sum = total(lst);
                        lst.step = pre.step + 1;
                        if(vis[sum].flag == 2)
                            continue;
                        if(vis[sum].flag == 1)
                            return lst.step + vis[sum].step;
                        vis[sum].flag = 2;
                        vis[sum].step = lst.step;
                        p.push(lst);
                    }
                }
                else if(i == 1){
                    for(t = 0; t < 2; t ++){
                        lst = pre;
                        lst.n[1] = pre.n[1] + dis[t];
                        if(lst.n[i] < 0)
                            lst.n[i] += 10;
                        else if(lst.n[i] >= 10)
                            lst.n[i] -= 10;
                        int temp = 0;
                        for(int j = 0; j < 6; j ++)
                            if(lst.n[j] % 2)
                                temp ++;
                            else
                                temp --;
                        if(temp != 0)
                            continue;
                        sum = total(lst);
                        lst.step = pre.step + 1;
                        if(vis[sum].flag == 2)
                            continue;
                        if(vis[sum].flag == 1)
                            return lst.step + vis[sum].step;
                        vis[sum].flag = 2;
                        vis[sum].step = lst.step;
                        p.push(lst);
                    }
                }
                else if(i == 2){
                    lst = pre;
                    lst.n[2] = pre.n[2] - 7;
                    if(lst.n[i] < 0)
                        lst.n[i] += 10;
                    else if(lst.n[i] >= 10)
                        lst.n[i] -= 10;
                    sum = total(lst);
                    lst. step = pre.step + 1;
                    if(vis[sum].flag == 2)
                        continue;
                    if(vis[sum].flag == 1)
                        return lst.step + vis[sum].step;
                    vis[sum].flag = 2;
                    vis[sum].step = lst.step;
                    p.push(lst);
                }
                else if(i == 3){
                    for(t = 0; t < 10; t ++){
                        lst.n[3] = pre.n[3] - t;
                        if(lst.n[i] < 0)
                            lst.n[i] += 10;
                        else if(lst.n[i] >= 10)
                            lst.n[i] -= 10;
                        int temp = 0;
                        for(int j = 0; j < 6; j ++){
                            temp += lst.n[j];
                        }
                        if(temp % 9 + 1 != i)
                            continue;
                        sum = total(lst);
                        lst.step = pre.step + 1;
                        if(vis[sum].flag == 2)
                            continue;
                        if(vis[sum].flag == 1)
                            return lst.step + vis[sum].step;
                        vis[sum].flag = 2;
                        vis[sum].step = lst.step;
                        p.push(lst);
                    }
                }
                else if(i == 4){
                    for(t = 0; t < 2; t ++){
                        lst = pre;
                        lst.n[4] = pre.n[4] + dis[t];
                        if(lst.n[i] < 0)
                            lst.n[i] += 10;
                        else if(lst.n[i] >= 10)
                            lst.n[i] -= 10;
                        if(lst.n[0] + lst.n[2] + lst.n[4] != 9)
                            continue;
                        sum = total(lst);
                        lst.step = pre.step + 1;
                        if(vis[sum].flag == 2)
                            continue;
                        if(vis[sum].flag == 1)
                            return lst.step + vis[sum].step;
                        vis[sum].flag = 2;
                        vis[sum].step = lst.step;
                        p.push(lst);
                    }
                }
                else if(i == 5 && pre.n[1] == 0){
                    lst = pre;
                    lst.n[5] = pre.n[5] + 3;
                    if(lst.n[i] < 0)
                        lst.n[i] += 10;
                    else if(lst.n[i] >= 10)
                        lst.n[i] -= 10;
                    sum = total(lst);
                    lst.step = pre.step + 1;
                    if(vis[sum].flag == 2)
                        continue;
                    if(vis[sum].flag == 1)
                        return lst.step + vis[sum].step;
                    vis[sum].flag = 2;
                    vis[sum].step = lst.step;
                    p.push(lst);
                }
            }
        }

        ++ sp;
    }
    return -1;
}

int T;


int main(void){

    char c;
    //freopen("out.txt", "r", stdin);
    //freopen("in.txt", "w",stdout);
    cin >> T;
    while(T --){
        bool flag = false;
        for(int i = 0; i < 6; i ++){
            cin >> ans[i];
            init[i] = 0;
            if(ans[i])
                flag = true;
        }
        if(!flag)
            cout << "0" << endl;
        int res = bfs();
        cout << res << endl;
    }
    return 0;


}


原文地址:https://www.cnblogs.com/chilumanxi/p/5136043.html