题解 P2741 【[USACO4.4]重叠的图像Frame Up】

· · 题解

题目由此去

一道非常恶心的题目(

以上为感受

题目大意:

$2.$ 这些框宽为$1$,每条边的长度都至少$3$。 $3.$ 求从底层至最上层的框顺序,有多个答案就按字典序输出 ------------ ### 分析: 再看分析之前要先保证回$string$和$char$的一些用法。 $First.$因为 “${\color{red}\colorbox{blue}{一个角同时属于两条边}}$”,于是我们保存每个矩形的左上角坐标与右下角坐标,就确定了整个矩形。 $Next.$可以看出,最上层的矩形是完整的,于是它可以作为本题突破口。 (一)从上层往底层,逐层搜索完整的矩形 $1.$ 按字符从大到小搜索矩形 $2.$ 当该矩形只含 “ . ” $or$ 该矩形的字母时,就是符合题意的。 $3.$ 若矩形符合题意,就将其字符放入栈中,然后全部变成 “ . ” , 删除该矩形 $4.$ ${\color{red}DFS}$:将当层删去的矩形恢复成删前的样子,注意不是恢复成输入时的样子。 ------------ 上代码: ``` #include <bits/stdc++.h> using namespace std; const int MAXX = 35; const int INF = 0x7fffffff/2; struct Nice { int x1 , y1 , x2 , y2; }tc[MAXX]; int h , w , cnt , cntans; char g[MAXX][MAXX] , c[MAXX] , ans[MAXX] , Ans[MAXX * MAXX][MAXX] , tp[MAXX]; bool v[MAXX] , flag[MAXX]; int dx[] = {1 , 0 , -1 , 0} , dy[] = {0 , 1 , 0 , -1}; bool cmp(int a , int b) { return a > b; } int Cmp(const void *a , const void *b) { char *s1 = (char *)a , *s2 = (char *)b; return strcmp(s1 , s2); } bool dfs(int x , int y , int xx , int yy) { if (x == tc[xx].x1 && y == tc[xx].y1 && yy == 3) { g[x][y] = '.'; return 1; } if (!(g[x][y] == '.' || g[x][y] - 'A' == xx)) { return 0; } if (x == tc[xx].x2 && y == tc[xx].y1 ) { if (dfs(x , y + 1 , xx , yy + 1)) { g[x][y] = '.'; return 1; } else return 0; } else if (x == tc[xx].x2 && y == tc[xx].y2 ) { if (dfs(x - 1 , y , xx , yy + 1)) { g[x][y] = '.'; return 1; } else return 0; } else if (x == tc[xx].x1 && y == tc[xx].y2 ) { if (dfs(x , y - 1 , xx , yy + 1)) { g[x][y] = '.'; return 1; } else return 0; } else { if (dfs(x + dx[yy] , y + dy[yy] , xx , yy)) { g[x][y] = '.'; return 1; } else return 0; } } void work(int x , int y , int xx , int yy) { g[x][y] = xx + 'A'; if(x == tc[xx].x1 && y == tc[xx].y1 && yy == 3) { return; } if(x == tc[xx].x2 && y == tc[xx].y1) { work(x , y + 1 , xx , yy+1); } else if(x == tc[xx].x2 && y == tc[xx].y2) { work(x - 1 , y , xx , yy + 1); } else if(x == tc[xx].x1 && y == tc[xx].y2) { work(x , y - 1 , xx , yy + 1); } else { work(x + dx[yy] , y + dy[yy] , xx , yy); } } void DFS(int xi , int yi) { if (yi == cnt) { for (int i=yi-1; i>=0; i-- ) { tp[yi - 1 - i] = ans[i]; } memcpy(Ans[cntans++ ] , tp , sizeof(tp)); return ; } for (int i=1; i<=cnt; i++ ) { if (!flag[i] && dfs(tc[c[i]].x1 , tc[c[i]].y1 , c[i] , 0)) { flag[i] = 1; ans[yi] = c[i] + 'A'; DFS(i , yi + 1); work(tc[c[i]].x1 , tc[c[i]].y1 , c[i] , 0); flag[i] = 0; } } } void Work() { for (int i=1; i<=h; i++) { scanf("%s",g[i] + 1); for(int j=1; j<=w; j++) { if(g[i][j] != '.') { int kkk=g[i][j] - 'A'; if(i < tc[kkk].x1 || j < tc[kkk].y1 ) { tc[kkk].x1 = min(tc[kkk].x1 , i); tc[kkk].y1 = min(tc[kkk].y1 , j); } if(i > tc[kkk].x2 || j > tc[kkk].y2 ) { tc[kkk].x2 = max(tc[kkk].x2 , i); tc[kkk].y2 = max(tc[kkk].y2 , j); } if(!v[kkk]) { v[kkk] = 1; c[++cnt] = kkk; } } } } } int main(void ) { scanf("%d %d",&h,&w); for (int i=0; i<26; i++ ) { tc[i].x1 = INF; tc[i].y1 = INF; tc[i].x2 = 0; tc[i].y2 = 0; } Work(); sort(c + 1 , c + cnt + 1 , cmp); DFS(-1 , 0); qsort(Ans , cntans , sizeof(char)*55 , Cmp); for (int i=0; i<cntans; i++ ) { cout << Ans[i]; } } /* in: 9 8 .CCC.... ECBCBB.. DCBCDB.. DCCC.B.. D.B.ABAA D.BBBB.A DDDDAD.A E...AAAA EEEEEE.. out: EDABC */ ``` 我:“AC!AC!AC!啊。。。WA*还RE。”很惨44分。 心想:RE改改就好。。。可是数组开大了RE的点又变成WA。。。 So!改! 经过思考:貌似要vector和stack。 额。。。在150多行的代码中加vector和stack。。。可海星。 中途对小号私信发泄。。。~~内容为【数据删除,请自行想象|A|】~~ 提出我最后的AC代码: ```cpp //stack(堆栈) 提供了堆栈的全部功能,也就是说实现了一个先进后出的 #include <bits/stdc++.h> #include <vector> #include<stack> using namespace std; const int MAXX = 50 + 5; const int INF = 0x3f3f3f3f; vector<string> Ans;//记录最终答案并用来排字典序 stack<char> mx;//储存旧图信息,方便回溯 //被逼无奈才用vector和stack struct Nice { int x1 , y1 , x2 , y2; }tc[MAXX]; int h , w , cnt , cntans; char g[MAXX][MAXX] , c[MAXX] , ans[MAXX] , tp[MAXX]; bool v[MAXX] , flag[MAXX]; int dx[4] = {1 , 0 , -1 , 0} , dy[4] = {0 , 1 , 0 , -1}; bool cmp(int a , int b) { return a > b; } bool dfs(int x , int y , int xx , int yy) { if (!(g[x][y] == '.' || g[x][y] - 'A' == xx)) { return 0; } if (x == tc[xx].x1 && y == tc[xx].y1 && yy == 3) { mx.push(g[x][y]) , g[x][y] = '.'; return 1; } if (x == tc[xx].x2 && y == tc[xx].y1 ) { if (dfs(x , y + 1 , xx , yy + 1)) { mx.push(g[x][y]) , g[x][y] = '.'; return 1; } else return 0; } else if (x == tc[xx].x2 && y == tc[xx].y2 ) { if (dfs(x - 1 , y , xx , yy + 1)) { mx.push(g[x][y]) , g[x][y] = '.'; return 1; } else return 0; } else if (x == tc[xx].x1 && y == tc[xx].y2 ) { if (dfs(x , y - 1 , xx , yy + 1)) { mx.push(g[x][y]) , g[x][y] = '.'; return 1; } else return 0; } else { if (dfs(x + dx[yy] , y + dy[yy] , xx , yy)) { mx.push(g[x][y]) , g[x][y] = '.'; return 1; } else return 0; } } void work(int x , int y , int xx , int yy) { g[x][y] = mx.top(); mx.pop(); if(x == tc[xx].x1 && y == tc[xx].y1 && yy == 3) { return; } if(x == tc[xx].x2 && y == tc[xx].y1) { work(x , y + 1 , xx , yy + 1); } else if(x == tc[xx].x2 && y == tc[xx].y2) { work(x - 1 , y , xx , yy + 1); } else if(x == tc[xx].x1 && y == tc[xx].y2) { work(x , y - 1 , xx , yy + 1); } else { work(x + dx[yy] , y + dy[yy] , xx , yy); } } void DFS(int xi , int yi) { if (yi == cnt) { string sss; for (int i=yi-1; i>=0; i-- ) { sss += ans[i]; } Ans.push_back(sss); sss.clear(); return ; } for (int i=1; i<=cnt; i++ ) { if (!flag[i]) { if (dfs(tc[c[i]].x1 , tc[c[i]].y1 , c[i] , 0)) { flag[i] = 1; ans[yi] = c[i] + 'A'; DFS(i , yi + 1); work(tc[c[i]].x1 , tc[c[i]].y1 , c[i] , 0); flag[i] = 0; } } } } void Work() { for (int i=0; i<h; i++) { scanf("%s",g[i]); for(int j=0; j<w; j++) { if(g[i][j] != '.') { int kkk = g[i][j] - 'A'; tc[kkk].x1 = min(tc[kkk].x1 , i); tc[kkk].y1 = min(tc[kkk].y1 , j); tc[kkk].x2 = max(tc[kkk].x2 , i); tc[kkk].y2 = max(tc[kkk].y2 , j); if(!v[kkk]) { v[kkk] = 1; c[++cnt] = kkk; } } } } } int main() { scanf("%d %d",&h,&w); for (int i=0; i<50; i++ ) { tc[i].x1 = INF; tc[i].y1 = INF; tc[i].x2 = 0; tc[i].y2 = 0; } Work(); sort(c + 1 , c + cnt + 1 , cmp); DFS(-1 , 0); sort(Ans.begin(),Ans.end()); for (int i=0; i<Ans.size() ; i++ ) { cout << Ans[i] << "\n"; } } /* in: 9 8 .CCC.... ECBCBB.. DCBCDB.. DCCC.B.. D.B.ABAA D.BBBB.A DDDDAD.A E...AAAA EEEEEE.. out: EDABC */ ``` 感觉是做复杂了。。。看来VC还是那样弱啊qwq #### 这篇题解都到这里了,求管理给过qwq