题目大意
在一个10*15的棋盘上
取棋子的规则是:
- 1.优先选择具有最大聚类的棋子
- 2.如果有多个最大聚类的,选择最左边的
- 3.如果最左边还是不能区分,选择最下面的
每步得分的计算方法是 (m−2)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;
}