• 【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
  • 相关阅读:
    使用某些 DOCTYPE 时会导致 document.body.scrollTop 失效
    VB.NET 笔记1
    知识管理系统Data Solution研发日记之一 场景设计与需求列出
    知识管理系统Data Solution研发日记之五 网页下载,转换,导入
    折腾了这么多年的.NET开发,也只学会了这么几招 软件开发不是生活的全部,但是好的生活全靠它了
    分享制作精良的知识管理系统 博客园博客备份程序 Site Rebuild
    知识管理系统Data Solution研发日记之四 片段式数据解决方案
    知识管理系统Data Solution研发日记之二 应用程序系列
    知识管理系统Data Solution研发日记之七 源代码与解决方案
    知识管理系统Data Solution研发日记之三 文档解决方案
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7638041.html
Copyright © 2020-2023  润新知