又是一个模拟题。。。。
给出一个棋盘,然后每次要去消除消除后能得到分数最多的棋子
每次消除的时候这个棋子和与它相邻(四联通)并且同色的棋子
(如果没有和他相邻并且同色的棋子,那这个棋子不可消除
如果有多个位置可以选择,更靠左的,要是还是有多个位置,选靠下的
消除之后把所有的棋子往下移,然后再往左靠拢
然后如果干掉所有的棋子了,分数+1000
大概就是这样(
----------------------------------我是代码的昏割线----------------------
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char map[30][30];
int huge[30][30];
bool vis[30][30];
const int dx[] = {1,0,-1,0};
const int dy[] = {0,-1,0,1};
const char none = '.';
void outhuge(){
for(int i=0;i<=10;i++)
for(int j=0;j<20;j++)
printf(j<19?"%d ":"%d\n",huge[i][j]);
}
void outmap(){
for(int i=0;i<=10;i++)
for(int j=0;j<20;j++)
printf(j<19?"%c ":"%c\n",map[i][j]);
}
int dffs(int x,int y){
int ret = 1;
vis[x][y]=true;
for(int d=0;d<4;d++){
int mx = x + dx[d];
int my = y + dy[d];
if(map[x][y] == map[mx][my] && vis[mx][my]==false){
ret += dffs(mx,my);
}
}
return ret;
}
void dfss(int x,int y,int hg){
huge[x][y]=hg;
for(int d=0;d<4;d++){
int mx = x + dx[d];
int my = y + dy[d];
if(map[x][y] == map[mx][my] && huge[mx][my]==-1){
dfss(mx,my,hg);
}
}
}
void clean(int x,int y){
char C = map[x][y];
map[x][y]=none;
for(int d=0;d<4;d++){
int mx = x + dx[d];
int my = y + dy[d];
if(map[mx][my]==C){
clean(mx,my);
}
}
}
bool getMax(int &x,int &y){
memset(huge,-1,sizeof(huge));
memset(vis,0,sizeof(vis));
for(int i=1;i<20;i++)
for(int j=1;j<20;j++){
if(huge[i][j]==-1 && map[i][j]!=none){
int hg = dffs(i,j);
dfss(i,j,hg);
}
}
x = y = 0;
for(int j=1;j<20;j++)
for(int i=10;i>0;i--)
if(huge[i][j] > huge[x][y])
x = i,y = j;
if(huge[x][y] < 2)
return false;
return true;
}
void dit(int t){
char list[20];
for(int i=0;i<20;i++)
list[i] = none;
int len = 0;
for(int i=10;i>0;i--){
if(map[i][t]!=none){
list[len++]=map[i][t];
map[i][t]=none;
}
}
for(int i=0;i<len;i++)
map[10-i][t] = list[i];
}
void downer(){
for(int i=1;i<20;i++)
dit(i);
}
void moveto(int st,int ed){
for(int i=10;i>0;i--){
map[i][st]=map[i][ed];
map[i][ed]=none;
}
}
int have(int st){
for(int i=st;i<20;i++)
if(map[10][i]!=none)
return i;
return -1;
}
void lefter(){
for(int i=1;i<20;i++)
if(map[10][i]==none){
int ed = have(i);
if(ed==-1)
return;
moveto(i,ed);
}
}
void solve(){
int cnt = 1;
int x,y;
int poi=0;
int left=150;
while(getMax(x,y)==true){
int num = huge[x][y];
left -= num;
poi += (num-2)*(num-2);
printf("Move %d at (%d,%d): removed %d balls of color %c, got %d points.\n",
cnt++,11-x,y,num,map[x][y],(num-2)*(num-2));
clean(x,y);
downer();
lefter();
// outmap();
}
if(left == 0)
poi += 1000;
printf("Final score: %d, with %d balls remaining.\n",poi,left);
}
int main(){
int t;
int icase = 1;
scanf("%d",&t);
while(t--){
printf("Game %d:\n\n",icase++);
for(int i=0;i<20;i++)
for(int j=0;j<20;j++)
map[i][j]=none;
for(int i=1;i<=10;i++){
scanf("%s",map[i]+1);
}
for(int i=0;i<=10;i++)
map[i][16]=none;
solve();
puts("");
}
return 0;
}
------------------------------关于代码我想说的---------------------------
两遍dfs来消棋子我也是没谁了
(不知道是不是这段时间在写C#的原因,一个地方思路卡住了就写一个函数。。。思路卡住了又写一个函数。。。
(如你所见这个代码函数是很多Orz
关于代码中迷的各种20,30:
其实只是我一时想不起来数据的范围然后随手糊上去。。。
反正只要比题中的数据范围大就好了(笑
10不是随手糊的。。是行数。。。