Flower Pots (CTU Open 2013 E题)

CTU Open 2013 的一道题
题意在另一份报告:http://blog.csdn.net/d_xcj/article/details/52752139

分析:
      和之前说的差不多,是一道比较复杂的搜索和模拟,主要是模拟比较烦人,写起来很长,要注意很多细节。
     我的想法很简单,先预处理出任意两种方块能组成的所有形状(状态不是很多),然后判断给出的2个yellow pots能组成的形状另外2个red pots是不是也能组成一样的形状,然后顺便把答案也记忆化。
     预处理的时候我是先把pot1压在边上,然后把pot2放到pot1周围,pot1、pot2的8种形态(初态、3次旋转、初态的翻转,再来3次旋转)都来一遍,然后把pot2压在边上,把pot1放到pot2周围。。。。(感觉重复还是会挺多 = =?,不过时限给得很宽,一般不会超时)
        不擅长写这么长的代码 QAQ,应该有更好的解法,不过没想出来

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
using namespace std;

typedef pair<int,int> pii;
typedef vector<int> VI;

const int N = 12;
const char POT[] = "FILNPTUVWXYZ";

vector<string> pot[N];

void table()
{
    pot[0].push_back(" ##");
    pot[0].push_back("## ");
    pot[0].push_back(" # ");

    pot[1].push_back("#");
    pot[1].push_back("#");
    pot[1].push_back("#");
    pot[1].push_back("#");
    pot[1].push_back("#");

    pot[2].push_back("# ");
    pot[2].push_back("# ");
    pot[2].push_back("# ");
    pot[2].push_back("##");

    pot[3].push_back(" #");
    pot[3].push_back(" #");
    pot[3].push_back("##");
    pot[3].push_back("# ");

    pot[4].push_back("##");
    pot[4].push_back("##");
    pot[4].push_back("# ");

    pot[5].push_back("###");
    pot[5].push_back(" # ");
    pot[5].push_back(" # ");


    pot[6].push_back("# #");
    pot[6].push_back("###");

    pot[7].push_back("#  ");
    pot[7].push_back("#  ");
    pot[7].push_back("###");

    pot[8].push_back("#  ");
    pot[8].push_back("## ");
    pot[8].push_back(" ##");

    pot[9].push_back(" # ");
    pot[9].push_back("###");
    pot[9].push_back(" # ");

    pot[10].push_back(" #");
    pot[10].push_back("##");
    pot[10].push_back(" #");
    pot[10].push_back(" #");

    pot[11].push_back("## ");
    pot[11].push_back(" # ");
    pot[11].push_back(" ##");
}

set<VI> smemery[N][N];
int ansmemery[N][N][N][N];
bool board[N][N];

void rotate(int &si, int &ei, int &sj, int &ej, bool &isrl)
{
    swap(si, ei);
    swap(si, sj);
    swap(ei, ej);
    isrl = !isrl;
}

void reverse(int &sj, int &ej)
{
    swap(sj, ej);
}

void GetPotConfig(int id, int &si, int &ei, int &sj, int &ej, bool &isrl)
{
    si = 0;
    ei = pot[id].size() - 1;
    sj = 0;
    ej = pot[id][0].size() - 1;
    isrl = true;
}

bool fill_p(int id, int si, int ei, int sj, int ej, bool isrl, int x, int y, int record = -1, bool rot = false)
{
    bool ok = true;
    int top = -1;
    static pii stk[N];
    int counter1 = si < ei ? 1 : -1;
    int counter2 = sj < ej ? 1 : -1;
    ei += counter1;
    ej += counter2;

    int i, j, tx, ty;
    for(i = si, tx = x; i != ei && ok; i += counter1, tx++)
        for(j = sj, ty = y; j != ej; j += counter2, ty++)
        {
            if(isrl && pot[id][i][j] == '#')
            {
                if(board[tx][ty])
                {
                    ok = false;
                    break;
                }
                board[tx][ty] = true;
                stk[++top] = pii(tx, ty);
            }
            else if(!isrl && pot[id][j][i] == '#')
            {
                if(board[tx][ty])
                {
                    ok = false;
                    break;
                }
                board[tx][ty] = true;
                stk[++top] = pii(tx, ty);
            }
        }

    if(record >= 0)
    {
        if(ok)
        {
            vector<int> sta;

            si = sj = 1e9;
            ei = ej = 0;
            isrl = true;

            for(i = 0; i < 10; i++)
                for(j = 0; j < 10; j++)
                {
                    if(board[i][j])
                    {
                        si = min(si, i);
                        sj = min(sj, j);
                        ei = max(ei, i);
                        ej = max(ej, j);
                    }
                }

            int x = si < ei ? 1 : -1;
            int y = sj < ej ? 1 : -1;
            int limit_i = ei + x;
            int limit_j = ej + y;

            sta.clear();

            for(i = si; i != limit_i; i += x)
            {
                for(j = sj; j != limit_j; j += y)
                {
                    if(isrl && board[i][j]) sta.push_back(true);
                    else if(!isrl && board[j][i]) sta.push_back(true);
                    else sta.push_back(false);
                }
            }
            sta.push_back(abs(ej - sj) + 1);
            if(id > record) swap(record, id);
            smemery[id][record].insert(sta);
        }

        while(top != -1)
        {
            board[stk[top].first][stk[top].second] = false;
            top--;
        }
    }

    return ok;
}


void _init(int a, int b)
{
    for(int k = 0; k < 2; k++)
    {
        int si, ei, sj, ej;
        bool isrl;
        int si2, sj2, ei2, ej2;
        bool isrl2;

        GetPotConfig(a, si, ei, sj, ej, isrl);
        GetPotConfig(b, si2, ei2, sj2, ej2, isrl2);
        int limit = max(ei2, ej2) + 1;

        for(int i = 0; i < 8; i++)
        {
            for(int k = 0; k <= limit; k++)
            {
                memset(board, false, sizeof(board));
                fill_p(a, si, ei, sj, ej, isrl, k, 0);

                GetPotConfig(b, si2, ei2, sj2, ej2, isrl2);
                for(int j = 0; j < 8; j++)
                {
                    int limit_x = abs(ei - si) + 2;
                    int limit_y = abs(ej - sj) + 2;

                    for(int x = 0; x < limit_x; x++)
                        for(int y = 0; y < limit_y; y++)
                        {
                            fill_p(b, si2, ei2, sj2, ej2, isrl2, x, y, a, !isrl);
                        }

                    rotate(si2, ei2, sj2, ej2, isrl2);
                    if(j == 3) reverse(sj2, ej2);
                }
            }
            rotate(si, ei, sj, ej, isrl);
            if(i == 3) reverse(sj, ej);
        }

        swap(a, b);
    }
}

void init()
{
    for(int i = 0; i < N; i++)
        for(int j = i; j < N; j++)
        {
            _init(i, j);
        }
}


void solve(char A, char B, char C, char D)
{
    int a = lower_bound(POT, POT + N, A) - POT;
    int b = lower_bound(POT, POT + N, B) - POT;
    int c = lower_bound(POT, POT + N, C) - POT;
    int d = lower_bound(POT, POT + N, D) - POT;

    if(a > b) swap(a, b);
    if(c > d) swap(c, d);

    int flag = ansmemery[a][b][c][d];

    if(flag == 1) puts("NO");
    else if(flag == 2) puts("YES");
    else
    {
        set<VI>::iterator it;
        for(it = smemery[a][b].begin(); it != smemery[a][b].end(); ++it)
        {
            if(smemery[c][d].count(*it))
            {
                flag = 1;
                break;
            }
        }
        ansmemery[a][b][c][d] = ansmemery[c][d][a][b] = flag + 1;
        if(flag) puts("YES");
        else puts("NO");
    }
}

int main()
{
    table();
    init();

    char a, b, c, d;
    while(scanf(" %c%c %c%c", &a, &b, &c, &d) != EOF)
    {
        solve(a, b, c, d);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值