battery -2SAT

题目大意:有个网格图,每个格子是
炮台:可以向上下’|‘或者左右’-‘发射激光(你来决定向上下还是左右)
镜子:两种’\‘或者’/’,成45°反射激光
障碍:’#’:激光遇到会消失。激光出边界也会消失。
空地:’.’
现在你要给每个炮台确定方向,使得不存在一个炮台能打到另一个炮台,并且每个空地至少被一个炮台的激光经过(激光可以相交)。
T ≤ 100 , n , m ≤ 50 T\le100,n,m\le50 T100,n,m50
题解:
不难发现如果不存在一个炮台击中另一个炮台,那么每个空地的水平方向不可能有两束来自不同炮台的激光,竖直同理。
因此先处理每个炮台不会轰到另一个炮台的可行方向,判定是否存在一个空地无法被到达,是否一个空地只被一个炮台的一个方向经过,还有就是一个空地是否两个方向会被不同的炮台经过(注意被同一个炮台的两个方向击中是另外一种情况,这时候这个空地需要被忽略),最后一种情况就是一个2SAT。

 
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
//P : choose LR; Q : choose UD
const int LEN=60,N=LEN*LEN*2,M=1000000;
int P[LEN][LEN],Q[LEN][LEN],vis[LEN][LEN];
pii las[LEN][LEN],mst[LEN][LEN];
char bd[LEN][LEN];stack<int> s;
struct edges{
    int to,pre;
}e[M];int h[N],etop,dfn[N],low[N],dfc,cc,sta[N],no_ans,bel[N],cant[N];
inline int add_edge(int u,int v) { return /*debug(u)sp,debug(v)ln,*/e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
int tarjan(int x)
{
    s.push(x),dfn[x]=low[x]=++dfc,sta[x]=1;
    for(int i=h[x],y;i;i=e[i].pre)
        if(!sta[y=e[i].to]) tarjan(y),low[x]=min(low[x],low[y]);
        else if(sta[y]==1) low[x]=min(low[x],dfn[y]);
    if(low[x]==dfn[x])
    {
        bel[x]=++cc,sta[x]=2;
        for(int y=s.top();y!=x;s.pop(),y=s.top())
            bel[y]=cc,sta[y]=2;s.pop();
    }
    return 0;
}
inline int trd(int &dx,int &dy,char c)
{
    if(c=='\\') swap(dx,dy);
    else{// '/'
        if(dx) dy=-dx,dx=0;
        else dx=-dy,dy=0;
    }
    return 0;
}
#define OK(i,j,n,m) ((i)>=1&&(i)<=(n)&&(j)>=1&&(j)<=(m)&&bd[i][j]!='#')
#define DO(i,j,p,q)\
        if(bd[i][j]=='/'||bd[i][j]=='\\') trd(dx,dy,bd[i][j]);\
        else if(bd[i][j]=='.'){\
            if(!vis[i][j]) mst[i][j]=mp(q,p);\
            else if(mst[i][j]!=mp(q,p)) mst[i][j]=mp(0,0);\
            if(!vis[i][j]) las[i][j]=mp(q,p);\
            else if(las[i][j]!=mp(q,p)&&las[i][j]!=mp(p,q)) add_edge(p,las[i][j].fir),add_edge(las[i][j].sec,q);\
            vis[i][j]=1;\
        }
#define GO(p,q,_dx,_dy) for(int dx=_dx,dy=_dy,i=x+dx,j=y+dy;OK(i,j,n,m);i+=dx,j+=dy) DO(i,j,p,q)
#define GOCANT(p,_dx,_dy) for(int dx=_dx,dy=_dy,i=x+dx,j=y+dy;OK(i,j,n,m);i+=dx,j+=dy)\
    if(bd[i][j]=='|'||bd[i][j]=='-') { cant[p]=1;break; }\
    else if(bd[i][j]=='/'||bd[i][j]=='\\') trd(dx,dy,bd[i][j]);
inline int getcant(int x,int y,int n,int m)
{
    int p=P[x][y],q=Q[x][y];
    GOCANT(p,0,1)GOCANT(p,0,-1)
    GOCANT(q,1,0)GOCANT(q,-1,0)
    if(cant[p]&&cant[q]) return no_ans=1;
    return 0;
}
inline int go(int x,int y,int n,int m)
{
//  cerr ln,debug(x)sp,debug(y)ln;
    int p=P[x][y],q=Q[x][y];cant[p]=cant[q]=0;
    getcant(x,y,n,m);if(no_ans) return 0;
    if(!cant[q]) { GO(p,q,1,0)GO(p,q,-1,0) }
    if(!cant[p]) { GO(q,p,0,1)GO(q,p,0,-1) }
    //debug(cant[p])sp,debug(cant[q])ln;
    return 0;
}
int main()
{
    for(int T=inn();T;T--)
    {
//      static int curT=0;cout<<++curT<<" ";
        int n=inn(),m=inn(),c=0;
        no_ans=0,etop=0;
        rep(i,1,n) scanf("%s",bd[i]+1);
        rep(i,1,n) rep(j,1,m) las[i][j]=mp(0,0),vis[i][j]=0;
        rep(i,1,n) rep(j,1,m)
        {
            if(bd[i][j]=='|'||bd[i][j]=='-')
                P[i][j]=++c,Q[i][j]=++c,h[c-1]=h[c]=0,go(i,j,n,m);
            else P[i][j]=0;
            if(no_ans) { printf("IMPOSSIBLE\n");goto END_LOOP; }
        }
    //  cerr ln;
        rep(i,1,n) rep(j,1,m) if(P[i][j])
        {
            if(cant[P[i][j]]) add_edge(P[i][j],Q[i][j]);//,debug(P[i][j])sp,debug(Q[i][j])ln;
            if(cant[Q[i][j]]) add_edge(Q[i][j],P[i][j]);//,debug(Q[i][j])sp,debug(P[i][j])ln;
        }
        rep(i,1,n) rep(j,1,m) if(bd[i][j]=='.'&&!vis[i][j])
        {   printf("IMPOSSIBLE\n");goto END_LOOP;   }
        rep(i,1,n) rep(j,1,m) if(bd[i][j]=='.'&&mst[i][j].sec)
            add_edge(mst[i][j].sec,mst[i][j].fir);
        memset(sta,0,sizeof(int)*(c+1)),dfc=0,cc=0;
        rep(i,1,c) if(!sta[i]) tarjan(i);
        for(int i=1,x,y;i<=n;i++) rep(j,1,m) if(P[i][j])
        {
            if((x=bel[P[i][j]])==(y=bel[Q[i][j]])) { printf("IMPOSSIBLE\n");goto END_LOOP; }
            else if(x<y) bd[i][j]='-';else bd[i][j]='|';
        }
        printf("POSSIBLE\n");
        rep(i,1,n) { rep(j,1,m) printf("%c",bd[i][j]);printf("\n"); }
        END_LOOP:continue;
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
lenovo.thinkpad.bios.flash.without.battery-patch是指联想ThinkPad电脑的BIOS刷新过程中取消使用电池的补丁。 BIOS是基本输入输出系统,负责连接硬件设备和操作系统。在某些情况下,用户可能需要更新或刷新BIOS以提升电脑性能或解决问题。通常,在刷新BIOS期间需要连接电池以保证供电稳定,以防止刷新过程中电源中断导致的损坏。 然而,有时用户在刷新BIOS时可能遇到无法充电或电池状态不佳的问题。为了解决这个问题,联想可能提供了lenovo.thinkpad.bios.flash.without.battery-patch这个补丁。 这个补丁可能在刷新BIOS时允许用户不连接电池,只使用电源适配器来完成刷新过程。这样用户可以暂时不使用电池,以确保刷新过程的顺利进行。使用这个补丁的目的是为了解决电池问题对BIOS刷新的影响,为用户提供更便利、安全的操作选项。 用户要注意的是,BIOS刷新是一项高风险操作,存在风险导致电脑无法启动或出现其他问题。在进行BIOS刷新之前,建议用户备份重要数据,并确保电脑接通稳定的电源。追求性能提升和问题解决之前,请详细阅读联想提供的BIOS刷新说明,并确认使用lenovo.thinkpad.bios.flash.without.battery-patch是否适合自己的情况。 总之,lenovo.thinkpad.bios.flash.without.battery-patch是联想提供的一个补丁,允许用户在刷新BIOS时不连接电池,以解决电池问题对刷新过程的影响,提供更便利、安全的操作选项。用户在使用该补丁前应当谨慎,并遵循相关操作说明,以避免不必要的风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值