把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

题解P6370 [COCI2006-2007#6] KAMEN

传送门 P6370 [COCI2006-2007#6] KAMEN

题意

比较简单就不详细解释了。
就是模拟石子下落,输出最终效果。

暴力 60

暴力模拟的代码应该是好敲的。
对于每一次,逐层下落,直至落至最后一层。
附赠代码。

#include <bits/stdc++.h>
//#define int long long
using namespace std;
const int N = 3e4+5;
const int M = 32;
int r,c,n;
char ma[N][M];
map<char,int >dy;
bool check(int a,int x) {
    if(dy[ma[a][x]]||dy[ma[a+1][x]]) return 0;
    else return 1;
}
signed main() {
    dy['O']=1;
    dy['X']=2;
    cin>>r>>c;
    for(int i=1; i<=r; ++i) {
        for(int j=1; j<=c; ++j) {
            cin>>ma[i][j];
        }
    }
    cin>>n;
    for(int i=1; i<=n; ++i) {
        int x;
        cin>>x;
        int now=1;
        for(now=1; now<=r; ++now) {
            if(now==r) break;
            if(ma[now+1][x]=='X') break;
            if(ma[now+1][x]=='.') continue;
            if(ma[now+1][x]=='O') {
                if(x>1&&check(now,x-1)) {
                    x--;
                    continue;
                }
                if(x<c&&check(now,x+1)) {
                    x++;
                    continue;
                }
                break;
            }
        }
        ma[now][x]='O';
    }
    for(int i=1; i<=r; ++i) {
        for(int j=1; j<=c; ++j) {
            cout<<ma[i][j];
        }
        cout<<endl;
    }
    return 0;
}

AC

可以看出,对于相同的下落点,每一次下落会有大量路程重复去刷。
以此为出发点。

用一个数组 $cnt[x] $ 表示从 $x$ 下落最终到达的层数。
用 $to[i][j]$ 表示从 $j$ 下落到第 $i$ 层到达的列。

当然,每一次下落路径并不是完全相同,也可能会受到其他下落的影响。
因此,我们对于每次受影响的列从原落点前一层开始更新一下。

AC代码

#include <bits/stdc++.h>
//#define int long long
using namespace std;
const int N = 3e4+5;
const int M = 100;
int n, m;
char ma[N][M];
int cnt[N];
int to[N][M];
bool check(int now,int x) {
    if(ma[now][x]=='.'&&ma[now+1][x]=='.') return 1;
    return 0;
}
void down(int x,int now,int st) {
    while(1) {
        cnt[st]=now;
        to[now][st]=x;
        if(ma[now+1][x]=='X') break;
        else if(ma[now+1][x]=='.'){} 
        else if(ma[now+1][x]=='O') {
            if((x>1)&&check(now,x-1)) x--;
            else if((x<m)&&check(now,x+1)) x++;
            else break;
        }
        now++;
    }
}
signed main() {
    cin>>n>>m;
    for(int i=1;i<=n;++i) {
        string s;
        cin>>s;
        for(int j=1;j<=m;++j) {
            ma[i][j]=s[j-1];
        }
    }
    for(int i=1;i<=m;++i) ma[n+1][i]='X';
    for(int i=1;i<=m;++i) {
        down(i,1,i);
    }
    int T;
    cin>>T;
    while (T--) {
        int x;
        cin>>x;
        ma[cnt[x]][to[cnt[x]][x]] ='O';
        for(int i=1;i<=m;++i) {
            if(ma[cnt[i]][to[cnt[i]][i]]=='O')
                down(to[cnt[i]-1][i],cnt[i]-1,i);
        }   
    } 
    for(int i=1;i<=n;++i) {
        for(int j=1;j<=m;++j ) {
            cout<<ma[i][j];
        }
        cout<<endl;
    }
    return 0;
}
posted @ 2022-12-29 19:10  djh0314  阅读(44)  评论(0)    收藏  举报  来源
浏览器标题切换
浏览器标题切换end