Ralph 往桌子上放了许多个有唯一颜色的矩形纸片(可以重叠),现在给出桌子的俯瞰图,输出Raplh往桌子上放方格的顺序,输出字典序最小的一种。
如果无解,那么输出“ERROR!”
思路
<1>通过标记每种颜色A,B的四个角来得到A和B的关系;
<2>最终可以得到A->B,(表示A在B下)C->D等关系再利用拓扑序来得到答案
//处理每一个颜色
void add(int t,int x,int y){
if(x<0||y<0||x>=mx2||y>=mx1||G[x][y]!=A[t].id)return;
G[x][y]='.';A[t].S.push_back((P){x,y});
int &x1=A[t].x1,&x2=A[t].x2,&y1=A[t].y1,&y2=A[t].y2;
if(x1==-1)x1=x2=x,y1=y2=y;
if(x<x1)x1=x;if(x2<x)x2=x;if(y<y1)y1=y;if(y2<y)y2=y;
add(t,x+1,y);add(t,x-1,y);add(t,x,y+1);add(t,x,y-1);
}
for(int i=0;i<mx2;i++)
for(int j=0;j<mx1;j++){
char nw=G[i][j];
if(nw=='.')continue;
if(!mark[nw]){
A[++num].id=nw;
c[nw]=num;
mark[nw]=1;
}add(c[nw],i,j);
}
//造出边
bool check(P A){
return A.x>=x1&&A.x<=x2&&A.y>=y1&&A.y<=y2;
}
for(int i=1;i<=num;i++){
x1=A[i].x1,x2=A[i].x2,y1=A[i].y1,y2=A[i].y2;
for(int a=x1;a<=x2;a++)
for(int b=y1;b<=y2;b++)
if(t[a][b]=='.')return F;
for(int j=1;j<=num;j++)
if(i!=j){
for(int c=0;c<A[j].S.size();c++)
if(check(A[j].S[c])){
dep[A[j].id]++;
to[A[i].id].push_back(A[j].id);break;
}
}
}
//形成拓扑序
priority_queue<char>Q;
for(int i=1;i<=num;i++)if(!dep[A[i].id])Q.push(-A[i].id);
while(!Q.empty()){
int a=-Q.top();Q.pop();
ans+=(char)a;
for(int i=0;i<to[a].size();i++){
int nx=to[a][i];
dep[nx]--;
if(!dep[nx])Q.push(-nx);
}
}