POJ 1128 Frame Stacking

来源:互联网 发布:移动虚拟网络运营商 编辑:程序博客网 时间:2024/06/06 14:28

/*

http://acm.pku.edu.cn/JudgeOnline/problem?id=1128

DFS回溯实现拓扑排序
*/

#include <iostream>
#include <memory>
#include <string>
#include <algorithm>
#define MAX_N 32
#define MAX_L 26
using namespace std;

char mapv[MAX_N + 1][MAX_N + 1];  //记录输入
char letter[MAX_L + 1];           //记录输入中输出的字母c, C - 'A' + 1
bool graph[MAX_L + 1][MAX_L + 1]; //graph[i][j] = true, 表示i frame 排在 j frame的上面
int rowN, colN, lNum, resNum;     //输入的行数,列数,lnum表述输入中出现的字母的类别数,resNum记录输出的结果数目
int pos[MAX_L + 1][4];            //记录各个字母上下左右的Index, 从1开始记录

bool v[MAX_L + 1];
//记录结果
struct node
{
    string seq;
    node()
    {
        seq = "";
    }
}res[200]; //从0开始存

void init()
{
    resNum = lNum = 0;
    memset(pos, 0, sizeof(pos));
    memset(graph, 0, sizeof(graph));
}

bool compare(const node n1, const node n2)
{
    if(n1.seq <= n2.seq)
        return true;
    return false;
}
void topSort(int layer, string seqStr)
{
    //排完了,每排一个字母,layer + 1, 直到排完所有的字母
    if(layer > lNum)
    {
        //记录结果
        res[resNum++].seq = seqStr;
        return;
    }
    int minCom = INT_MAX, s, k, curL, curCom;
    int minNum = 0;
    //向temp这类数据必须使用局部数据,应为没一层的temp必须不能受其他层影响,
    //一开把temp设成了全局的,这样进入下一层后,下一层可能会修改上面层的temp,从而产生错误结果
    int temp[MAX_L + 1];

    //寻找入度最小的点,这个点对应的frame应该是放在最上面的frame(可能不唯一,所以会产生多个结果)
    for(s = 0; s < lNum; s++)
    {
        //当前结点是上面已经处理过已经被抹去的点
        if(letter[s] == '.')
            continue;
        curCom = 0;
        curL = letter[s] - 'A' + 1;
        for(k = 1; k <= MAX_L; k++)
            if(graph[k][curL])
                curCom++;
        //找到更小入度的点
        if(curCom < minCom)
        {
            minCom = curCom;
            minNum = 1;
            temp[minNum] = curL; //temp 从1开始存
        }
        //和最小度数相等,则记录,并使minNum + 1
        else if(curCom == minCom)
        {
            temp[++minNum] = curL;
        }
    }
    //回溯遍历所有的当前入度最小的点
    seqStr = "." + seqStr;
    for(s = 1; s <= minNum; s++)
    {
        curL = temp[s];
        //copyR和copyC也必须是局部数,原因和temp相同
        bool copyR[MAX_L + 1], copyC[MAX_L + 1];
        memset(copyR, 0, sizeof(copyR));
        memset(copyC, 0, sizeof(copyC));
        //保存当前节点对应的数据,并置位
        for(k = 1; k <= MAX_L; k++)
        {
            copyR[k] = graph[curL][k];
            copyC[k] = graph[k][curL];
            graph[curL][k] = graph[k][curL] = false;
        }
        seqStr[0] = curL - 1 + 'A';

        //已经处理过的节点要摸去
        int tempPos;
        for(k = 0; k < lNum; k++)
        {
            if(letter[k] == curL - 1 + 'A')
            {
                tempPos = k;
                letter[k] = '.';
                break;
            }
        }
        //dfs
        topSort(layer + 1, seqStr);
        //恢复相关数据
        letter[tempPos] = curL - 1 + 'A';
        for(k = 1; k <= MAX_L; k++)
        {
            graph[curL][k] = copyR[k];
            graph[k][curL] = copyC[k];
        }
    }
}
int main()
{
    int i, j, k;
    char c, cc;
    while(cin>>rowN)
    {
        cin>>colN;
        //input process
        init();
        for(i = 1; i <= rowN; i++)
        {
            for(j = 1; j <= colN; j++)
            {
                cin>>c;
                mapv[i][j] = c;
                if(c >= 'A' && c <= 'Z')
                {
                    for(k = 0; k < lNum; k++)
                        if(letter[k] == c)
                            break;
                    if(k >= lNum)
                        letter[lNum++] = c;
                }
            }
        }
        ///////////寻找每个frame最上方和最下方的行号,已经最左边和最右边的列号
        int s, p0, p1, p2, t, curL;
        //扫描行
        for(i = 1; i <= rowN; i++)
        {
            //扫描任意列
            for(j = 1; j <= colN; j++)
            {
                c = mapv[i][j];
                cc = mapv[rowN - i + 1][j];
                if(c >= 'A' && c <= 'Z')
                {
                    if(pos[c - 'A' + 1][0] == 0)
                        pos[c - 'A' + 1][0] = i;
                }
                if(cc >= 'A' && cc <= 'Z')
                {
                    if(pos[cc - 'A' + 1][1] == 0)
                        pos[cc - 'A' + 1][1] = rowN - i + 1;
                }
            }
        }
        //列扫描
        for(i = 1; i <= colN; i++)
        {
            //扫描任意行
            for(j = 1; j <= rowN; j++)
            {
                c = mapv[j][i];
                cc = mapv[j][colN - i + 1];
                if(c >= 'A' && c <= 'Z')
                {
                    if(pos[c - 'A' + 1][2] == 0)
                        pos[c - 'A' + 1][2] = i;
                }
                if(cc >= 'A' && cc <= 'Z')
                {
                    if(pos[cc - 'A' + 1][3] == 0)
                        pos[cc - 'A' + 1][3] = colN - i + 1;
                }
            }
        }
        ///////////顺次处理每个节点s,如果在s的四条边线中夹杂有其他节点t,那么表示
        //t遮住了s, graph[t][s] 设置为true
        for(s = 0; s < lNum; s++)
        {
            curL = letter[s] - 'A' + 1;
            memset(v, 0, sizeof(v));

            for(i = 0; i < 4; i++)
            {
                p0 = pos[curL][i];
                int j = ((int(i / 2) + 1) * 2) % 4;
                p1 = pos[curL][j];
                p2 = pos[curL][j + 1];

                for(t = p1; t <= p2; t ++)
                {
                    if(i <= 1)
                    {
                        if(mapv[p0][t] == letter[s])
                            continue;
                        if(v[mapv[p0][t] - 'A' + 1])
                            continue;
                        if(!(mapv[p0][t] >= 'A' && mapv[p0][t] <= 'Z'))
                            continue;
                        v[mapv[p0][t] - 'A' + 1] = true;
                        graph[mapv[p0][t] - 'A' + 1][curL] = true;
                    }
                    else
                    {
                        if(mapv[t][p0] == letter[s])
                            continue;
                        if(v[mapv[t][p0] - 'A' + 1])
                            continue;
                        if(!(mapv[t][p0] >= 'A' && mapv[t][p0] <= 'Z'))
                            continue;
                        v[mapv[t][p0] - 'A' + 1] = true;
                        graph[mapv[t][p0] - 'A' + 1][curL] = true;
                    }
                }
               
            }
        }
        string str = "";
        topSort(1, str);
        sort(res, res + resNum, compare);
        for(i = 0; i < resNum; i++)
            cout<<res[i].seq<<endl;
        /////////////////
    }
    return 0;
}

原创粉丝点击