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去处理输入输出了。。。