問題描述
消除類遊戲是深受大衆歡迎的一種遊戲,遊戲在一個包含有n行m列的遊戲棋盤上進行,棋盤的每一行每一列的方格上放着一個有顏色的棋子,當一行或一列上有連續三個或更多的相同顏色的棋子時,這些棋子都被消除。當有多處可以被消除時,這些地方的棋子將同時被消除。
現在給你一個n行m列的棋盤,棋盤中的每一個方格上有一個棋子,請給出經過一次消除後的棋盤。
請注意:一個棋子可能在某一行和某一列同時被消除。
輸入格式
輸入的第一行包含兩個整數n, m,用空格分隔,分別表示棋盤的行數和列數。
接下來n行,每行m個整數,用空格分隔,分別表示每一個方格中的棋子的顏色。顏色使用1至9編號。
輸出格式
輸出n行,每行m個整數,相鄰的整數之間使用一個空格分隔,表示經過一次消除後的棋盤。如果一個方格中的棋子被消除,則對應的方格輸出0,否則輸出棋子的顏色編號。
樣例輸入
4 5
2 2 3 1 2
3 4 5 1 4
2 3 2 1 3
2 2 2 4 4
樣例輸出
2 2 3 0 2
3 4 5 0 4
2 3 2 0 3
0 0 0 4 4
樣例說明
棋盤中第4列的1和第4行的2可以被消除,其他的方格中的棋子均保留。
樣例輸入
4 5
2 2 3 1 2
3 1 1 1 1
2 3 2 1 3
2 2 3 3 3
樣例輸出
2 2 3 0 2
3 0 0 0 0
2 3 2 0 3
2 2 0 0 0
樣例說明
棋盤中所有的1以及最後一行的3可以被同時消除,其他的方格中的棋子均保留。
評測用例規模與約定
所有的評測用例滿足:1 ≤ n, m ≤ 30。
解題思路:
利用結構體來存可以消去的元素的座標,最後遍歷結構體數組將二維數組賦0;調試時注意邊界,結構體數組大小也很關鍵。我的存儲方式決定了找3連比較時的方式,所以還是比較麻煩。
令一種方法是建立另外一個標記型二維數組,把符合條件的在標記數組上做標記,最後對比標記數組來改變輸入的數組。這種存儲方式可以利用以下方法進行比較:
for(i=0; i<n; i++)
for(j=0; j<m-2; j++)
if(a[i][j]== a[i][j + 1] && a[i][j + 1] == a[i][j +2])
我的方法與大佬的差太多,還需要繼續鍛鍊,以下是我的滿分代碼:
#include<iostream>
using namespace std;
int a[32][32];
int m,n;
struct node{
int s;
int l;
int ss;
}que1[500],que2[500];//數組開小了,一直90分。注意!
int main(){
cin>>n>>m;
int res;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>a[i][j];
}
}
int cnt=1;
int cou1=0,cou2=0;
for(int i=0;i<n;i++){
//一行中
cnt=1;
for(int j=m-1;j>=0;j--){
if(j&&a[i][j]==a[i][j-1]){
cnt++;
}
if(j&&cnt<3&&a[i][j-1]!=a[i][j]){
cnt=1;
}
//cout<<"cnt:"<<cnt<<" J:"<<j<<endl;
if(cnt>=3&&(j==0||a[i][j-1]!=a[i][j])){
que1[cou1].s=j;
que1[cou1].ss=i;//位於哪一行
que1[cou1].l=cnt;
//cout<<"l "<<que1[cou1].l<<endl;
cou1++;
cnt=1;
}
}
}
//cout<<"**"<<que1[0].l<<endl;
for(int i=0;i<m;i++){//一列中
cnt=1;
for(int j=n-1;j>=0;j--){
if(j&&a[j][i]==a[j-1][i]){
cnt++;
}
if(j&&cnt<3&&a[j-1][i]!=a[j][i]){
cnt=1;
}
if(cnt>=3&&(a[j-1][i]!=a[j][i]||j==0)){
que2[cou2].s=j;
que2[cou2].l=cnt;
que2[cou2].ss=i;//位於哪一列
cou2++;
cnt=1;
}
}
}
/*cout<<"cout1 "<<cou1<<endl;
cout<<"l "<<que1[0].l<<endl;
cout<<"ss "<<que1[0].ss<<endl;;*/
for(int i=0;i<cou1;i++){//消除一行
for(int j=0;j<que1[i].l;j++){
a[que1[i].ss][que1[i].s+j]=0;
}
}
for(int i=0;i<cou2;i++){//消除一列
for(int j=0;j<que2[i].l;j++){
//cout<<"**"<<endl;
a[que2[i].s+j][que2[i].ss]=0;
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
/*
4 5
6 9 8 8 8
9 9 9 1 8
6 9 1 1 8
6 2 6 1 6
//注意邊邊角角的樣例
*/
第二遍做有了好思路,把每一個點的判定當作一個模塊,然後利用迭代進行操作即可,在鏡像數組中標記應該清零的數,最後輸出時結合其進行輸出即可。
但是當我把g【】【】數組開城g【50】【50】才得60分,當我把g定義爲【1000】【1000】纔可以的滿分。這裏還不知道爲何,需要注意!
#include<iostream>
#include<cstdio>
using namespace std;
int g[1010][1010];
int tmp[50][50];
int n,m;
void deal(int x,int y,int z){
if(g[x][y]!=z) return ;
if((x<n-1||x>0)&&g[x+1][y]==z&&g[x-1][y]==z){
tmp[x][y]=z;
if(tmp[x+1][y]!=z){
tmp[x+1][y]=z;
deal(x+1,y,z);
}
if(tmp[x-1][y]!=z){
tmp[x-1][y]=z;
deal(x-1,y,z);
}
}
if((y<m-1||y>0)&&g[x][y+1]==z&&g[x][y-1]==z){
tmp[x][y]=z;
if(tmp[x][y+1]!=z){
tmp[x][y+1]=z;
deal(x,y+1,z);
}
if(tmp[x][y-1]!=z){
tmp[x][y-1]=z;
deal(x,y-1,z);
}
}
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>g[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
deal(i,j,g[i][j]);
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(tmp[i][j]){
cout<<0<<" ";
}
else {
cout<<g[i][j]<<" ";
}
}
cout<<endl;
}
return 0;
}