POJ 1027 The Same Game棋盘游戏(模拟)

POJ 1027 The Same Game

题目大意

在一个10*15的棋盘上
这里写图片描述
取棋子的规则是:

  • 1.优先选择具有最大聚类的棋子
  • 2.如果有多个最大聚类的,选择最左边的
  • 3.如果最左边还是不能区分,选择最下面的

每步得分的计算方法是 (m2)2 ,m为取走的棋子数,如果最后全部取走再加上1000分

总结

第一次样例都没看仔细就交了WA(以后交的时候一定要仔细检查依一下样例),改了后TLE,测试了一下发现不是死循环的原因(ps.在代码中可能会出现死循环的地方放个语句超过一定的循环次数就直接输出个错误答案,如果是死循环结果就应该是WA而不是TLE)
然后看了别人的题解说有因为queue超时的,改了后900ms+险过,以后用STL都要注意一点了。

代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
using namespace std;
int board[13][18];//board[c][r]表示第几行第几列,1表示R,2表示G,3表示B
int cluster[13][18];//求出每个棋子的聚类数
int bj[13][18];
int x[4]={1,-1,0,0};
int y[4]={0,0,-1,1};
int Case=0;
int Qr[150];//从1开始
int Qc[150];
int Qr_head,Qr_tail,Qc_head,Qc_tail;
void In()
{
    char c;
    for(int i=10;i>=1;i--)
        for(int j=1;j<=15;j++)
        {
                scanf("%c",&c);
                while(c=='\n' || c==' ')scanf("%c",&c);
                if(c=='R') board[i][j]=1;
                else if(c=='G') board[i][j]=2;
                else if(c=='B') board[i][j]=3;
        }
}
void Travel()
{
    cout<<endl;
    for(int i=10;i>=1;i--)
    {
          for(int j=1;j<=15;j++)
          {
                if(board[i][j]==1)cout<<'R';
                else if(board[i][j]==2)cout<<'G';
                else if(board[i][j]==3)cout<<'B';
                else cout<<board[i][j];
          }
          cout<<endl;
    }
}
void Travel_cluster()
{
    cout<<endl;
    for(int i=10;i>=1;i--)
    {
          for(int j=1;j<=15;j++)
          {
              cout<<cluster[i][j]<<" ";
          }
          cout<<endl;
    }
}
void Update_node(int rr,int cc)//更新一个点的聚类值
{
     int Class=board[rr][cc];
     Qr_head=1;Qr_tail=0;
     Qc_head=1;Qc_tail=0;
     bj[rr][cc]=2;//为了区分暂时标记为2
     int cnt=1;
     Qr[++Qr_tail]=rr;
     Qc[++Qc_tail]=cc;

     while(Qr_tail>=Qr_head)
     {
           int tr=Qr[Qr_head++];
           int tc=Qc[Qc_head++];
           for(int k=0;k<=3;k++)
           {
                 int Tr=tr+x[k];
                 int Tc=tc+y[k];
                 if(Tr>=1 && Tr<=10 && Tc>=1 &&Tc<=15)//判断下一点是否出界
                 {
                       if(board[Tr][Tc]==Class && bj[Tr][Tc]==0)
                       {
                             Qr[++Qr_tail]=Tr;
                             Qc[++Qc_tail]=Tc;
                             bj[Tr][Tc]=2;//为了区分暂时标记为2
                             cnt++;
                       }
                 }
           }
     }

     for(int i=1;i<=10;i++)
     {
           for(int j=1;j<=15;j++)
           {
                 if(bj[i][j]==2)
                 {
                       bj[i][j]=1;
                       cluster[i][j]=cnt;
                 }
           }
     }
}
void Update_cluster()//更新每个点的聚类值
{
       memset(bj,0,sizeof(bj));
       memset(cluster,0,sizeof(cluster));
       for(int i=1;i<=10;i++)
       {
             for(int j=1;j<=15;j++)
             {
                   if(bj[i][j]==0 && board[i][j]!=0)Update_node(i,j);
             }
       }
}
void Find_loc(int &rr,int &cc)//找到将要移去的聚类棋子的位置,如果找不到则为(0,0)
{
    int x[18];//x[j]表示第j列最大的值的所在的行
    memset(x,0,sizeof(x));
    int maxm=0;
    int flag=0;//0表示找不到
    for(int j=1;j<=15;j++)
    {
          maxm=0;
          for(int i=15;i>=1;i--)
          {
                if(cluster[i][j]>=2)flag=1;
                if(cluster[i][j]>=maxm){x[j]=i;maxm=cluster[i][j];}

          }
    }
    if(flag==0){rr=0,cc=0;return ;}
    int loc=15;//找到最大的所在列
    for(int  j=14;j>=1;j--)
    {
          if(cluster[x[j]][j]>=cluster[x[loc]][loc]){loc=j;}
    }
    rr=x[loc];
    cc=loc;
}
int Remove(int rr,int cc)//移去(rr,cc)的聚类棋子,并返回移去的棋子数
{
     int ans=0;
     memset(bj,0,sizeof(bj));
     int Class=board[rr][cc];
     //queue<int> Qr;
     //queue<int> Qc;
     Qr_head=1;Qr_tail=0;
     Qc_head=1;Qc_tail=0;
     bj[rr][cc]=1;
     ans=1;
     //Qr.push(rr);Qc.push(cc);
     Qr[++Qr_tail]=rr;
     Qc[++Qc_tail]=cc;

     while(Qr_tail>=Qr_head)
     {


           //int tr=Qr.front();
           //int tc=Qc.front();
           //Qr.pop();Qc.pop();
           int tr=Qr[Qr_head++];
           int tc=Qc[Qc_head++];
           for(int k=0;k<=3;k++)
           {
                 int Tr=tr+x[k];
                 int Tc=tc+y[k];
                 if(Tr>=1 && Tr<=10 && Tc>=1 && Tc<=15)//判断下一点是否出界
                 {
                       if(board[Tr][Tc]==Class && bj[Tr][Tc]==0)
                       {
                             Qr[++Qr_tail]=Tr;
                             Qc[++Qc_tail]=Tc;
                             bj[Tr][Tc]=1;
                             ans++;
                       }
                 }
           }
     }
     for(int i=1;i<=10;i++)
           for(int j=1;j<=15;j++)
                 if(bj[i][j]==1){board[i][j]=0;cluster[i][j]=0;}
     return ans;
}
void Move_down()//每一列往下移动
{
    int loc;
    for(int j=1;j<=15;j++)
    {
          loc=1;
          for(int i=1;i<=10;i++)
          {
                if(board[i][j]!=0)
                {
                      if(i!=loc){board[loc][j]=board[i][j];board[i][j]=0;}
                      loc++;
                }
          }
    }

}
void Move_left()//以列为单位往左移动
{
     int x[18];//x[j]表示第j列需要往左移动x[j]步
     int t=0;
     int flag;
     for(int j=1;j<=15;j++)
     {
           flag=0;//flag=0表示这一列为空
           for(int i=1;i<=10;i++)
                 if(board[i][j]!=0){flag=1;break;}
           x[j]=t;
           if(flag==0)t++;
    }
     for(int j=1;j<=15;j++)
           for(int i=1;i<=10;i++)
           {
                 if(x[j]!=0)
                 {
                     board[i][j-x[j]]=board[i][j];
                     board[i][j]=0;
                 }
           }
}
void Work()
{

      int rr,cc;
      int t;
      int ans=0;
      char color;
      int Step=0;

      while(1)
      {
          //getchar();
          Update_cluster();//更新每个点的聚类值
          //Travel_cluster();
          Find_loc(rr,cc);//找到将要移去的聚类棋子的位置,如果找不到则为(0,0)
          //cout<<rr<<" "<<cc<<endl;
          if(cluster[rr][cc]<2)break;
          if(board[rr][cc]==1)color='R';
          else if(board[rr][cc]==2)color='G';
          else color='B';
          t=Remove(rr,cc);//移去(rr,cc)的聚类棋子,并返回移去的棋子数
          printf("Move %d at (%d,%d): removed %d balls of color ",++Step,rr,cc,t);
          printf("%c",color);
          printf(", got %d points.\n",(t-2)*(t-2));
          ans+=(t-2)*(t-2);
          //更新棋子位置
          Move_down();//每一列往下移动
          Move_left();//以列为单位往左移动
          //Travel();
      }

      int left=0;//全部移完则为0
      for(int i=1;i<=10;i++)
          for(int j=1;j<=15;j++)
                if(board[i][j]!=0) left++;
      if(left==0)ans+=1000;
      printf("Final score: %d, with %d balls remaining.\n",ans,left);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        In();
        //Travel();
        printf("Game %d:\n\n",++Case);
        Work();
        if(T!=0)printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值