Frame Up[USACO]

这道题没什么难度,开始看错了,以为要输出的是从上到下的顺序。我用的dfs,尝试把一个个矩形从当前图中拿出来,拿出来后将所在位置置为'*',在下次循环时需要恢复未拿走时的字符串。

 

/*
ID: zhangyc1
LANG: C++
TASK: frameup
*/
#include <fstream>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;

ofstream fileout("frameup.out");

bool arrAppear[26], arrCheck[26];
int nNumCh = 0;
char arrChSort[26];
stringstream ss;
vector<string> vtString;
struct SPosition 
{
    int nTop, nBot, nLft, nRht;
    SPosition():nTop(31),nBot(0),nLft(31),nRht(0){}
};
SPosition arrPos[26];
int H, W;
char arrMatrix[30][30];

void prepairData()
{
    memset(arrAppear, 0, sizeof(arrAppear));
    ifstream filein("frameup.in");
    filein >> H >> W;
    for (int i = 0; i < H; i++)
    {
        for (int j = 0; j < W; j++)
        {
            filein >> arrMatrix[i][j];
            if (arrMatrix[i][j] == '.')
                continue;

            int nIdx = arrMatrix[i][j] - 'A';
            if (!arrAppear[nIdx])
            {
                arrAppear[nIdx] = true;
                nNumCh++;
            }
            
            if (i < arrPos[nIdx].nTop)
            {
                arrPos[nIdx].nTop = i;
            }
            if (j < arrPos[nIdx].nLft)
            {
                arrPos[nIdx].nLft = j;
            }
            if (i > arrPos[nIdx].nBot)
            {
                arrPos[nIdx].nBot = i;
            }
            if (j > arrPos[nIdx].nRht)
            {
                arrPos[nIdx].nRht = j;
            }
        }
    }
    filein.close();
}

void RemoveChar(int idx, char arrBackup[4][30])
{
    memcpy(arrBackup[0], arrMatrix[arrPos[idx].nTop] + arrPos[idx].nLft, arrPos[idx].nRht - arrPos[idx].nLft + 1);
    memcpy(arrBackup[1], arrMatrix[arrPos[idx].nBot] + arrPos[idx].nLft, arrPos[idx].nRht - arrPos[idx].nLft + 1);

    memset(arrMatrix[arrPos[idx].nTop] + arrPos[idx].nLft, (int)'*', arrPos[idx].nRht - arrPos[idx].nLft + 1);
    memset(arrMatrix[arrPos[idx].nBot] + arrPos[idx].nLft, (int)'*', arrPos[idx].nRht - arrPos[idx].nLft + 1);
    for (int i = arrPos[idx].nTop + 1; i < arrPos[idx].nBot; i++)
    {
        arrBackup[2][i] = arrMatrix[i][arrPos[idx].nLft];
        arrBackup[3][i] = arrMatrix[i][arrPos[idx].nRht];
        arrMatrix[i][arrPos[idx].nLft] = '*';
        arrMatrix[i][arrPos[idx].nRht] = '*';
    }
}
void RestoreChar(int idx, char arrBackup[4][30])
{
    memcpy(arrMatrix[arrPos[idx].nTop] + arrPos[idx].nLft, arrBackup[0], arrPos[idx].nRht - arrPos[idx].nLft + 1);
    memcpy(arrMatrix[arrPos[idx].nBot] + arrPos[idx].nLft, arrBackup[1], arrPos[idx].nRht - arrPos[idx].nLft + 1);
    for (int i = arrPos[idx].nTop + 1; i < arrPos[idx].nBot; i++)
    {
        arrMatrix[i][arrPos[idx].nLft] = arrBackup[2][i];
        arrMatrix[i][arrPos[idx].nRht] = arrBackup[3][i];
    }
}

void MoveUp(int idx)
{
    if (idx == nNumCh)
    {
        for (int i = nNumCh - 1; i >= 0; i--)
        {
            ss << arrChSort[i];
        }
        string str;
        ss >> str;
        ss.clear();
        vtString.push_back(str);
        return;
    }

    for (int i = 0; i < 26; i++)
    {
        if (!arrAppear[i] || arrCheck[i])
            continue;
        bool bValid = true;
        char ch = 'A' + i;
        for (int j = arrPos[i].nLft; j <= arrPos[i].nRht; j++)
        {
            if ((arrMatrix[arrPos[i].nTop][j] != ch && arrMatrix[arrPos[i].nTop][j] != '*') || (arrMatrix[arrPos[i].nBot][j] != ch && arrMatrix[arrPos[i].nBot][j] != '*'))
            {
                bValid = false;
                break;
            }
        }
        for (int j = arrPos[i].nTop; j <= arrPos[i].nBot && bValid; j++)
        {
            if ((arrMatrix[j][arrPos[i].nLft] != ch && arrMatrix[j][arrPos[i].nLft] != '*') || (arrMatrix[j][arrPos[i].nRht] != ch && arrMatrix[j][arrPos[i].nRht] != '*'))
            {
                bValid = false;
                break;
            }
        }
        if (!bValid)
            continue;
        arrChSort[idx] = ch;
        arrCheck[i] = true;
        char arrBackup[4][30];
        RemoveChar(i, arrBackup);
        MoveUp(idx + 1);
        RestoreChar(i, arrBackup);
        arrCheck[i] = false;
    }
}

void process()
{
    MoveUp(0);
    sort(vtString.begin(), vtString.end());
    for (vector<string>::const_iterator iter = vtString.begin(); iter != vtString.end(); iter++)
    {
        fileout << *iter << endl;
    }
}

int main(){
    prepairData();
    process();
    fileout.close();
    return 0;
}

提交之后,最后一个测试例要0.3秒,很不满意,看了一下大家的方法。确实,这题用拓扑排序的方式很适合,直接输出的就是字典序(相比上个方法省掉了快排的时间)。

/*
ID: zhangyc1
LANG: C++
TASK: frameup
*/
#include <fstream>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;



bool arrAppear[26];
int nNumCh = 0;
struct SPosition 
{
    int nTop, nBot, nLft, nRht;
    SPosition():nTop(31),nBot(0),nLft(31),nRht(0){}
};
SPosition arrPos[26];
int H, W;
char arrMatrix[30][31];
struct SNode 
{
    int nIndex;
    SNode* pNext;
    SNode():nIndex(-1), pNext(NULL){}
    SNode(int n):nIndex(n), pNext(NULL){}
};
SNode* arrHead[26];
SNode* arrTail[26];
int arrInNum[26];
bool arrUsed[26];
char strRs[27];

void prepairData()
{
    freopen("frameup.in","r",stdin);

    memset(arrAppear, 0, sizeof(arrAppear));
    memset(arrHead, 0, sizeof(arrHead));
    memset(arrHead, 0, sizeof(arrTail));
    memset(arrInNum, 0, sizeof(arrInNum));
    memset(arrUsed, 0, sizeof(arrUsed));

    scanf("%d%d",&H,&W);

    for (int i = 0; i < H; i++)
    {
        scanf("%s",arrMatrix[i]);
        for (int j = 0; j < W; j++)
        {
            if (arrMatrix[i][j] == '.')
                continue;

            int nIdx = arrMatrix[i][j] - 'A';
            if (!arrAppear[nIdx])
            {
                arrAppear[nIdx] = true;
                nNumCh++;
            }

            if (i < arrPos[nIdx].nTop)
                arrPos[nIdx].nTop = i;
            if (j < arrPos[nIdx].nLft)
                arrPos[nIdx].nLft = j;
            if (i > arrPos[nIdx].nBot)
                arrPos[nIdx].nBot = i;
            if (j > arrPos[nIdx].nRht)
                arrPos[nIdx].nRht = j;
        }
    }
}

void AddNode(int nFrom, int nTo)
{
    arrInNum[nTo]++;
    if (arrHead[nFrom] == NULL)
    {
        arrHead[nFrom] = new SNode(nTo);
        arrTail[nFrom] = arrHead[nFrom];
    }
    else
    {
        arrTail[nFrom]->pNext = new SNode(nTo);
        arrTail[nFrom] = arrTail[nFrom]->pNext;
    }
}

void BulidLinkList()
{
    for (int i = 0; i < 26; i++)
    {
        if (!arrAppear[i])
            continue;
        char ch = 'A' + i;
        bool bCheck[26] = {false};
        for (int j = arrPos[i].nLft; j <= arrPos[i].nRht; j++)
        {
            if (arrMatrix[arrPos[i].nTop][j] != ch && !bCheck[arrMatrix[arrPos[i].nTop][j] - 'A'])
            {
                bCheck[arrMatrix[arrPos[i].nTop][j] - 'A'] = true;
                AddNode(i, arrMatrix[arrPos[i].nTop][j] - 'A');
            }
            if (arrMatrix[arrPos[i].nBot][j] != ch && !bCheck[arrMatrix[arrPos[i].nBot][j] - 'A'])
            {
                bCheck[arrMatrix[arrPos[i].nBot][j] - 'A'] = true;
                AddNode(i, arrMatrix[arrPos[i].nBot][j] - 'A');
            }
        }
        for (int j = arrPos[i].nTop; j <= arrPos[i].nBot; j++)
        {
            if (arrMatrix[j][arrPos[i].nLft] != ch && !bCheck[arrMatrix[j][arrPos[i].nLft] - 'A'])
            {
                bCheck[arrMatrix[j][arrPos[i].nLft] - 'A'] = true;
                AddNode(i, arrMatrix[j][arrPos[i].nLft] - 'A');
            }
            if (arrMatrix[j][arrPos[i].nRht] != ch && !bCheck[arrMatrix[j][arrPos[i].nRht] - 'A'])
            {
                bCheck[arrMatrix[j][arrPos[i].nRht] - 'A'] = true;
                AddNode(i, arrMatrix[j][arrPos[i].nRht] - 'A');
            }
        }

    }
}

ofstream fout("frameup.out");

void TopologySort(int nDepth)
{
    if (nDepth == nNumCh)
    {
        for (int i = 0; i < nNumCh; i++)
        {
            //fout << strRs[i];
            printf("%c",strRs[i]);
        }
        printf("\n");;
        //fout << endl;
        return;
    }

    for (int i = 0; i < 26; i++)
    {
        if (!arrAppear[i] || arrUsed[i] || arrInNum[i] != 0)
            continue;
        strRs[nDepth] = 'A' + i;
        arrUsed[i] = true;
        SNode* pNode = arrHead[i];
        while (pNode)
        {
            arrInNum[pNode->nIndex]--;
            pNode = pNode->pNext;
        }
        TopologySort(nDepth + 1);
        arrUsed[i] = false;
        pNode = arrHead[i];
        while (pNode)
        {
            arrInNum[pNode->nIndex]++;
            pNode = pNode->pNext;
        }
    }
}

void process()
{
    BulidLinkList();
    TopologySort(0);
}

int main(){
    freopen("frameup.out","w",stdout);
    prepairData();
    process();
    return 0;
}

提交之后,发现还是0.3秒。基于对ofstream 的怀疑,改成用scanf和printf。果然,

Test 9: TEST OK [0.022 secs, 3368 KB]

 

 

于是,我只把上次提交的版本的fout改成printf

Test 9: TEST OK [0.076 secs, 3372 KB]

决定以后还是用cstdio去处理输入输出了。。。

posted @ 2013-04-16 14:45  J.Z's World  阅读(219)  评论(0编辑  收藏  举报