UVa 1533:Moving Pegs(迭代加深搜索)

題目鏈接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=842&page=show_problem&problem=4308

分析:如圖所示,一共有15個洞,其中一個空着,剩下的洞裏各有一個小球。每次可以讓一個小球越過同一條直線上的一個或多個連續的小球,落到最近的空洞(不能越過空洞),然後拿走被跳過的小球。例如,讓14調到空洞5中,則洞9裏的小球會被拿走,因此操作之後洞9和14會變空,而5裏面會有一個小球。你的任務是用最少的步數讓整個棋盤只剩下一個小球,並且位於初始時的那個空洞中。(本段摘自《算法競賽入門經典(第2版)》)

分析:
       使用迭代加深搜索,事先在常量數組裏存好可以跳的地方和會經過的棋子。處理起來方便一點。

代碼:

#include <iostream>
#include <algorithm>
#include <fstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <cctype>
#include <stack>
#include <set>

using namespace std;

const int maxn = 15 + 5, INF = 10;

const int z[16][6] = {
{},
{ 4, 6, 7,10,11,15},
{ 7, 9,11,14},
{ 8,10,12,15},
{ 1, 6,11,13},
{12,14},
{ 1, 4,13,15},
{ 1, 2, 9,10},
{ 3,10},
{ 2, 7},
{ 1, 3, 7, 8},
{ 1, 2, 4, 13,14,15},
{ 3, 5,14,15},
{ 4, 6,11,15},
{ 2, 5,11,12},
{ 1, 3, 6,11,12,13}
};

const int WAY[100][3] = {
{ 1, 4, 2},{ 1, 6, 3},{ 1, 7, 2},{ 1, 7, 4},{ 1,10, 3},{ 1,10, 6},{ 1,11, 2},{ 1,11, 4},{ 1,11, 7},{ 1,15, 3},{ 1,15, 6},{ 1,15,10},
{ 2, 7, 4},{ 2, 9, 5},{ 2,11, 4},{ 2,11, 7},{ 2,14, 5},{ 2,14, 9},
{ 3, 8, 5},{ 3,10, 6},{ 3,12, 5},{ 3,12, 8},{ 3,15, 6},{ 3,15,10},
{ 4, 1, 2},{ 4, 6, 5},{ 4,11, 7},{ 4,13, 8},
{ 5,12, 8},{ 5,14,9},
{ 6, 1, 3},{ 6, 4, 5},{ 6,13, 9},{6, 15,10},
{ 7, 1, 2},{ 7, 1, 4},{ 7, 2, 4},{ 7, 9, 8},{ 7,10, 8},{ 7,10, 9},
{ 8, 3, 5},{ 8,10, 9},
{ 9, 2, 5},{ 9, 7, 8},
{10, 1, 3},{10, 1, 6},{10, 3, 6},{10, 7, 8},{10, 7, 9},{10, 8, 9},
{11, 1, 2},{11, 1, 4},{11, 1, 7},{11, 2, 4},{11, 2, 7},{11, 4, 7},{11,13,12},{11,14,12},{11,14,13},{11,15,12},{11,15,13},{11,15,14},
{12, 3, 5},{12, 3, 8},{12, 5, 8},{12,14,13},{12,15,13},{12,15,14},
{13, 4, 8},{13, 6, 9},{13,11,12},{13,15,14},
{14, 2, 5},{14, 2, 9},{14, 5, 9},{14,11,12},{14,11,13},{14,12,13},
{15, 1, 3},{15, 1, 6},{15, 1,10},{15, 3, 6},{15, 3,10},{15, 6,10},{15,11,12},{15,11,13},{15,11,14},{15,12,13},{15,12,14},{15,13,14}
};

int T, x;
int v[maxn], path[maxn][2];
vector< int > vec[maxn];
vector< int > way[maxn][maxn];

void init()
{
    for (int i = 1; i <= 15; ++i)
    {
        for (int j = 0; j < 6; ++j)
            if (z[i][j])
                vec[i].push_back(z[i][j]);
    }
    for (int i = 0; i < 100; ++i)
        way[WAY[i][0]][WAY[i][1]].push_back(WAY[i][2]);
}

bool judge()
{
    for (int i = 1; i <= 15; ++i)
        if ((i == x && !v[i]) || (i != x && v[i]))
            return false;
    return true;
}

bool jump(int x, int y)
{
    for (int i = 0; i < way[x][y].size(); ++i)
        if (!v[way[x][y][i]])
            return false;
    return true;
}

void remove(int x, int y)
{
    for (int i = 0; i < way[x][y].size(); ++i)
        v[way[x][y][i]] = 0;
    v[x] = 0;
    v[y] = 1;
}

void recover(int x, int y)
{
    for (int i = 0; i < way[x][y].size(); ++i)
        v[way[x][y][i]] = 1;
    v[x] = 1;
    v[y] = 0;
}

bool DFS(int deep, int limit)
{
    if (deep == limit)
    {
        if (judge())
        {
            printf("%d\n", limit);
            for (int i = 0; i < limit; ++i)
                if (i < limit - 1)
                    printf("%d %d ", path[i][0], path[i][1]);
                else
                    printf("%d %d\n", path[i][0], path[i][1]);
            return true;
        }
        return false;
    }
    for (int i = 1; i <= 15; ++i)
    {
        if (v[i])
        {
            for (int j = 0; j < vec[i].size(); ++j)
            {
                int u = vec[i][j];
                if (!v[u] && jump(i, u))
                {
                    remove(i, u);
                    path[deep][0] = i;
                    path[deep][1] = u;
                    if (DFS(deep + 1, limit))
                        return true;
                    recover(i, u);
                }
            }
        }
    }
    return false;
}

int main()
{
    init();
    scanf("%d", &T);
    for (int C = 0; C < T; ++C)
    {
        scanf("%d", &x);
        for (int i = 1; i <= 15; ++i)
            if (i == x)
                v[i] = 0;
            else
                v[i] = 1;
        for (int maxd = 1; ; ++maxd)
            if (DFS(0, maxd))
                break;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章