P6370 [COCI2006-2007#6] KAMEN 题解
原题链接:P6370
思路
题意不多赘述。
首先这道题的 \(60\) 分暴力很好打,直接按题目中的操作做即可,时间复杂度 \(O(nr)\)。
考虑优化暴力。我们会发现很多次石头的起始点为同一列的情况,其实每一次下落的轨迹是差不多的。具体来讲应该是第一次下落的轨迹一定包含了后面每一次的轨迹。所以我们可以模拟一个类似于栈的东西 \(s_{i,j}\) 表示起始点在第 \(i\) 列,当前在第 \(j\) 行(即跳过的步数为 \(j\),因为每跳一次一定下落一行)时,当前在 \(s_{i,j}\) 列。那么,对于起始点在每一列的情况,第一次直接暴力将栈填满,之后的每一次再看栈顶的位置合不合法,如果不合法的话就弹出直到合法为止。则栈顶的位置就是这颗石头所在的位置。
因为起始点只可能有 \(O(c)\) 个,且对于每个起始点的暴力操作最多 \(O(rc)\) 次,于是总时间复杂度 \(O(rc^{2}\))。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f
#define inf_db 127
#define ls id << 1
#define rs id << 1 | 1
#define re register
#define endl '\n'
typedef pair <int,int> pii;
const int MAXN = 3e4 + 10;
const int MAXM = 30 + 10;
int n,m,q,x,s[MAXM][MAXN],cnt[MAXN];
char c[MAXN][MAXM];
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i = 1;i <= n;i = -~i) scanf("%s",(c[i] + 1));
for(int i = 1;i <= m;i = -~i) c[n + 1][i] = 'X';
for(int i = 1;i <= m;i++) s[i][++cnt[i]] = i;
scanf("%lld",&q);
while(q--)
{
scanf("%lld",&x);
while(true)
{
int now = s[x][cnt[x]];
//x 表示最开始时的列数,now 表示当前的列数(即跳过的步数),cnt[x] 表示当前的行数
if(c[cnt[x]][now] == 'O') cnt[x]--;
else if(cnt[x] >= n) break;
else if(c[cnt[x] + 1][now] == 'X') break;
else if(c[cnt[x] + 1][now] == '.') s[x][++cnt[x]] = now;
else if(c[cnt[x]][now - 1] == '.' && c[cnt[x] + 1][now - 1] == '.') s[x][++cnt[x]] = now - 1;
else if(c[cnt[x]][now + 1] == '.' && c[cnt[x] + 1][now + 1] == '.') s[x][++cnt[x]] = now + 1;
else break;
}
c[cnt[x]][s[x][cnt[x]]] = 'O';
}
for(int i = 1;i <= n;i = -~i) printf("%s\n",(c[i] + 1));
return 0;
}
本文作者:Creeper_l
本文链接:https://www.cnblogs.com/Creeperl/p/17913416.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步