SRM 550 TopView

11 篇文章 0 订阅
1 篇文章 0 订阅

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);
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值