• 【Luogu】P3930 SAC E#1


    【题目】洛谷10月月赛R1 提高组

    【题意】给定n*n棋盘和<=16个棋子,给几个棋子种类和攻击范围,现我方只有一马,求能否吃王。

    【算法】状压+BFS

    【题解】16种棋子中,马不能吃马,直接处理马和王,那么就剩13个棋子,可以压成2^13表示棋盘现有棋子存活状态。

    然后对vis[2^13][n][n]进行bfs。

    细节:

    1.攻击直到碰到其它棋子,那个碰到的棋子也算攻击范围内。

    2.判断碰到棋子时,注意该棋子是否在当前局面存活。

    3.多组数据,Q中途退出要清空。

    学到了:

    1.一份长代码要细心经营,视若珍宝,动键盘之前要冷静把思路和框架理清楚,过程中步步为营,慢慢写总能写完的。

    2.不要轻易相信自己的代码没有bug了,尽量对拍,把小数据的中间结果输出和手算比较正确性,从而改掉尽可能多的错误。

    3.不要害怕写长的复杂的代码,先做框架,然后一步一步把子过程做好,一份超长代码就慢慢构造出来了。

    4.枚举对角线的姿势!

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int inf=0x3f3f3f3f,maxn=60;
    int n,mp[1<<14][maxn][maxn],map[maxn][maxn],p[maxn][maxn],ans;
    int cnt,tot,Tx,Ty,Sx,Sy;
    bool vis[1<<14][maxn][maxn];
    struct Node{int x,y;}c[15],ch[15];
    struct cyc{int S,x,y,st;};
    queue<cyc>Q;
    void qishi(int S,int x,int y){
        mp[S][x-1][y+2]=mp[S][x+1][y+2]=mp[S][x+2][y-1]=mp[S][x+2][y+1]=1;
        if(x-2>0)mp[S][x-2][y-1]=mp[S][x-2][y+1]=1;
        if(y-2>0)mp[S][x-1][y-2]=mp[S][x+1][y-2]=1;
    }
    void king(int S,int x,int y){
        mp[S][x-1][y-1]=mp[S][x-1][y]=mp[S][x-1][y+1]=1;
        mp[S][x][y-1]=mp[S][x][y+1]=1;
        mp[S][x+1][y-1]=mp[S][x+1][y]=mp[S][x+1][y+1]=1;
    }
    bool m(int S,int x,int y){
        if(map[x][y]<=1)return 1;
        if(map[x][y]==2||map[x][y]==7)return 0;
        if(S&(1<<(p[x][y]-1)))return 0;
        return 1;
    }
    void chengbao(int S,int x,int y){
        for(int i=x-1;i>=1;i--)if(m(S,i,y))mp[S][i][y]=1;else{mp[S][i][y]=1;break;}
        for(int i=x+1;i<=n;i++)if(m(S,i,y))mp[S][i][y]=1;else{mp[S][i][y]=1;break;}
        for(int i=y-1;i>=1;i--)if(m(S,x,i))mp[S][x][i]=1;else{mp[S][x][i]=1;break;}
        for(int i=y+1;i<=n;i++)if(m(S,x,i))mp[S][x][i]=1;else{mp[S][x][i]=1;break;}
    }
    void zhujiao(int S,int x,int y){
        for(int i=1;i<min(x,y);i++)if(m(S,x-i,y-i))mp[S][x-i][y-i]=1;else{mp[S][x-i][y-i]=1;break;}
        for(int i=1;i<=min(n-x,n-y);i++)if(m(S,x+i,y+i))mp[S][x+i][y+i]=1;else{mp[S][x+i][y+i]=1;break;}
        for(int i=1;i<=min(x,n-y);i++)if(m(S,x-i,y+i))mp[S][x-i][y+i]=1;else{mp[S][x-i][y+i]=1;break;}
        for(int i=1;i<=min(n-x,y);i++)if(m(S,x+i,y-i))mp[S][x+i][y-i]=1;else{mp[S][x+i][y-i]=1;break;}
    }
    void soldier(int S,int x,int y){
        mp[S][x+1][y-1]=mp[S][x+1][y+1]=1;
    }
    void check(int S,int x,int y,int st){
        if(x<1||x>n||y<1||y>n||mp[S][x][y]||vis[S][x][y])return;
        vis[S][x][y]=1;
        if(map[x][y]==2)ans=st;
        if(map[x][y]>=3&&map[x][y]<=6)if(S&(1<<(p[x][y]-1)))S^=(1<<(p[x][y]-1));
        vis[S][x][y]=1;
        Q.push((cyc){S,x,y,st});
    }
    char s[maxn];
    int main(){
    while(scanf("%d",&n)==1){
        cnt=tot=0;
        memset(map,0,sizeof(map));memset(p,0,sizeof(p));memset(mp,0,sizeof(mp));memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            for(int j=1;j<=n;j++){
                if(s[j]=='K')map[i][j]=7,c[++cnt].x=i,c[cnt].y=j;
                if(s[j]=='X')map[i][j]=2,Tx=i,Ty=j,c[++cnt].x=i,c[cnt].y=j;
                if(s[j]=='O')Sx=i,Sy=j;
                if(s[j]=='C')map[i][j]=3,ch[tot].x=i,ch[tot].y=j,p[i][j]=tot++;
                if(s[j]=='B')map[i][j]=4,ch[tot].x=i,ch[tot].y=j,p[i][j]=tot++;
                if(s[j]=='Q')map[i][j]=5,ch[tot].x=i,ch[tot].y=j,p[i][j]=tot++;
                if(s[j]=='P')map[i][j]=6,ch[tot].x=i,ch[tot].y=j,p[i][j]=tot++;
            }
        }
        for(int S=0;S<(1<<tot);S++){
            for(int i=1;i<=cnt;i++)if(map[c[i].x][c[i].y]==7)qishi(S,c[i].x,c[i].y);else king(S,c[i].x,c[i].y);
            for(int i=0;i<tot;i++)if((1<<i)&S){
                int x=ch[i].x,y=ch[i].y;
                if(map[x][y]==3)chengbao(S,x,y);
                if(map[x][y]==4)zhujiao(S,x,y);
                if(map[x][y]==5)chengbao(S,x,y),zhujiao(S,x,y);
                if(map[x][y]==6)soldier(S,x,y);
            }
            mp[S][Tx][Ty]=0;
        }
        if(mp[(1<<tot)-1][Sx][Sy]==1){printf("-1
    ");continue;}
        while(!Q.empty())Q.pop();
        Q.push((cyc){(1<<tot)-1,Sx,Sy,0});vis[(1<<tot)-1][Sx][Sy]=1;
        ans=0;
        while(!Q.empty()){
            cyc q=Q.front();Q.pop();
            check(q.S,q.x-2,q.y-1,q.st+1);check(q.S,q.x-2,q.y+1,q.st+1);
            check(q.S,q.x-1,q.y-2,q.st+1);check(q.S,q.x-1,q.y+2,q.st+1);
            check(q.S,q.x+1,q.y-2,q.st+1);check(q.S,q.x+1,q.y+2,q.st+1);
            check(q.S,q.x+2,q.y-1,q.st+1);check(q.S,q.x+2,q.y+1,q.st+1);
            if(ans)break;
        }
        if(ans==0)printf("-1
    ");else printf("%d
    ",ans);
    }
    return 0;
    }
    View Code
  • 相关阅读:
    Expression Bland 入门视频(五) 了解对象面板和属性面板
    Windows Phone 一步一步从入门到精通
    “北京今年入冬的第一场雪”,纪念博客园写日志一年了
    2010年即将到来,用我的名字注册了的新域名 TerryFeng.com
    我要在黑龙江的老家,组织一个微软.Net俱乐部
    Windows 7 小工具 问题步骤记录器
    给弟弟起步学习软件开发(.Net 方向)的指导,博友们帮助看看,提些意见给他。
    今天是中国传统节日“重阳节”。也是爷爷的生日,今年80岁高龄。
    Windows 7 远程服务器管理工具 简体中文 下载
    新的技术和概念应该尽可能先去接受,而不是排斥。
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7638041.html
Copyright © 2020-2023  润新知