Codevs 1004 四子连棋

题目:

http://codevs.cn/problem/1004/

题解:
基本上算是抄的黄学长的qwq
http://hzwer.com/848.html
黄学长的bfs写的炒鸡棒

tips:
不要过分依赖于stl里的queue,有的时候手打队列更方便。
把重复部分写成函数调用。
为什么棋盘hash不需要考虑当前走到那个颜色???
hzwer学长好像是没有考虑
我觉得要考虑吖
codevs数据太水,也看不出对错来23333333333

代码:

不考虑颜色
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int inf=1005000;
const int mod=9875321;
bool hve[10000050];
char q[inf][5][5];
char a[5][5];
int dx[]={0,0,1,0,-1},dy[]={0,1,0,-1,0};
int stp[inf],lst[inf];
int ans=-1,head,tail;
bool can(int pos,int x,int y){
    if(x<=0||x>4||y<=0||y>4) return 0;
    if(q[pos][x][y]=='B'&&lst[pos]==0)  return 0;
    if(q[pos][x][y]=='W'&&lst[pos]==1) return 0;
    return 1;
}
int gethash(char a[5][5]){
    int key=0;
    int t=0;
    for(int i=1;i<=4;i++){
        for(int j=1;j<=4;j++){
            if(a[i][j]=='B') t=0;
            if(a[i][j]=='W') t=1;
            if(a[i][j]=='O') t=2;
            key=(key*3+t)%mod;
        }
    }
    return key;
}
bool same(char a,char b,char c,char d){
    if((a==b)&&(b==c)&&(c==d)) return 1;
    return 0;
}
bool ys(char a[5][5]){
    for(int i=1;i<=4;i++){
        if(same(a[i][1],a[i][2],a[i][3],a[i][4])) return 1;
        if(same(a[1][i],a[2][i],a[3][i],a[4][i])) return 1;
    }
    if(same(a[1][1],a[2][2],a[3][3],a[4][4])) return 1;
    if(same(a[1][4],a[2][3],a[3][2],a[4][1])) return 1;
    return 0;
}
void move(int pos,int x,int y){
    for(int i=1;i<=4;i++){
        int xx=x+dx[i],yy=y+dy[i];
        if(!can(pos,xx,yy)) continue;//边界,黑白, 
        for(int s=1;s<=4;s++){
            for(int t=1;t<=4;t++)
            a[s][t]=q[pos][s][t];
        }
        a[x][y]=q[pos][xx][yy];
        a[xx][yy]='O';
        int hsh=gethash(a);//判重 
        if(hve[hsh]) continue;
        hve[hsh]=1;
        if(ys(a)) {
            ans=stp[pos]+1;
            return ;
        }
        tail++;
        for(int s=1;s<=4;s++){
            for(int t=1;t<=4;t++) 
            q[tail][s][t]=a[s][t];
        }
        lst[tail]=(lst[pos]^1);
        stp[tail]=stp[pos]+1;
    }
    return ;
}
void bfs(){
    head=0;tail=1;
    while(head<=tail){
        for(int i=1;i<=4;i++){
            for(int j=1;j<=4;j++){
                if(q[head][i][j]=='O') move(head,i,j);
            }
        }
        if(ans!=-1) return ;
        head++;
    }
}
int main(){
    for(int i=1;i<=4;i++){
        cin>>a[i]+1;
        for(int j=1;j<=4;j++){
            q[1][i][j]=q[0][i][j]=a[i][j];
        }
    }
    int hsh=gethash(a);
    hve[hsh]=1;
    lst[0]=0;lst[1]=1;
    stp[0]=0;stp[1]=0;
    bfs();
    printf("%d\n",ans);
/*  for(int i=0;i<=tail;i++){
        for(int s=1;s<=4;s++){
            for(int t=1;t<=4;t++) printf("%c",q[i][s][t]);
            printf("\n");
        }
        printf(" %d \n",stp[i]);
    }*/
    return 0;
}
考虑颜色
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int inf=1005000;
const int mod=9875321;
bool hve[10000050];
char q[inf][5][5];
char a[5][5];
int dx[]={0,0,1,0,-1},dy[]={0,1,0,-1,0};
int stp[inf],lst[inf];
int ans=-1,head,tail;
bool can(int pos,int x,int y){
    if(x<=0||x>4||y<=0||y>4) return 0;
    if(q[pos][x][y]=='B'&&lst[pos]==0)  return 0;
    if(q[pos][x][y]=='W'&&lst[pos]==1) return 0;
    return 1;
}
int gethash(int last,char a[5][5]){//考虑颜色
    int key=last;
    int t=0;
    for(int i=1;i<=4;i++){
        for(int j=1;j<=4;j++){
            if(a[i][j]=='B') t=0;
            if(a[i][j]=='W') t=1;
            if(a[i][j]=='O') t=2;
            key=(key*3+t)%mod;
        }
    }
    return key;
}
bool same(char a,char b,char c,char d){
    if((a==b)&&(b==c)&&(c==d)) return 1;
    return 0;
}
bool ys(char a[5][5]){
    for(int i=1;i<=4;i++){
        if(same(a[i][1],a[i][2],a[i][3],a[i][4])) return 1;
        if(same(a[1][i],a[2][i],a[3][i],a[4][i])) return 1;
    }
    if(same(a[1][1],a[2][2],a[3][3],a[4][4])) return 1;
    if(same(a[1][4],a[2][3],a[3][2],a[4][1])) return 1;
    return 0;
}
void move(int pos,int x,int y){
    for(int i=1;i<=4;i++){
        int xx=x+dx[i],yy=y+dy[i];
        if(!can(pos,xx,yy)) continue;//边界,黑白, 
        for(int s=1;s<=4;s++){
            for(int t=1;t<=4;t++)
            a[s][t]=q[pos][s][t];
        }
        a[x][y]=q[pos][xx][yy];
        a[xx][yy]='O';
        int hsh=gethash(lst[pos],a);//判重 
        if(hve[hsh]) continue;
        hve[hsh]=1;
        if(ys(a)) {
            ans=stp[pos]+1;
            return ;
        }
        tail++;
        for(int s=1;s<=4;s++){
            for(int t=1;t<=4;t++) 
            q[tail][s][t]=a[s][t];
        }
        lst[tail]=(lst[pos]^1);
        stp[tail]=stp[pos]+1;
    }
    return ;
}
void bfs(){
    head=0;tail=1;
    while(head<=tail){
        for(int i=1;i<=4;i++){
            for(int j=1;j<=4;j++){
                if(q[head][i][j]=='O') move(head,i,j);
            }
        }
        if(ans!=-1) return ;
        head++;
    }
}
int main(){
    for(int i=1;i<=4;i++){
        cin>>a[i]+1;
        for(int j=1;j<=4;j++){
            q[1][i][j]=q[0][i][j]=a[i][j];
        }
    }
    int hsh=gethash(1,a);
    hve[hsh]=1;
    hsh=gethash(0,a);
    hve[hsh]=1;
    lst[0]=0;lst[1]=1;
    stp[0]=0;stp[1]=0;
    bfs();
    printf("%d\n",ans);
/*  for(int i=0;i<=tail;i++){
        for(int s=1;s<=4;s++){
            for(int t=1;t<=4;t++) printf("%c",q[i][s][t]);
            printf("\n");
        }
        printf(" %d \n",stp[i]);
    }*/
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值