小球下落(暴力,模拟)

题目描述
有一块大小为n行2列的板子,每个位置可能是一个小球,用’o’表示,可能是障碍物,用’x’表示,也可能空无一物,用’.'来表示。
每个小球可以向左向右或者向下移动,但是不能向上移动,或者和某个小球重叠,也不能越出板子。
每个小球向下移动一个单位,牛牛可以获得一分。
输入
第一行输入一个整数n,表示板子的行数。
随后n行,每行一个长度为2的字符串,如题意所示。
设有k个小球。
输出
一行,一个整数,表示牛牛能得到的最大分数。

样例输入

10
oo
.o
.x
x.
..
oo
.o
x.
..
x.

样例输出

12

提示
样例解释
最终结果为:

oo
ox
x.



x.
oo
xo。

对于20%的数据有n≤3。
另有20%的数据k≤10。
对于60%的数据有n≤1000。
对于100%的数据有1≤n≤300000。

思路:

一开始还以为是BFS,其实不是

直接从下往上遍历一遍即可,对于每个小球,尽可能地往下移
如果不能往下移了,那么看看移到旁边是否能继续往下移
当移不动时,如果旁边的顶上是'x',并且旁边有空位的情况下,要移到旁边去

AC代码

#include <iostream>
#include <vector>
 
using namespace std;
 
typedef long long ll;
 
ll n,ans;
char Map[300010][2];
bool exist[300010][2];
 
 
bool check(ll x,ll y)
{
    if(x <= n && Map[x][y] == '.') return 1;
    return 0;
}
 
void BFS(ll x,ll y)
{
    while(check(x+1,y))
    {
        swap(Map[x][y],Map[x+1][y]);
        x++;
        ans++;
    }
    if(y == 0)
    {
        if(check(x,1) && check(x+1,1))
        {
            swap(Map[x][0],Map[x][1]);
            y = 1;
            BFS(x,y);
        }
        else if(check(x,1) && Map[x-1][1] == 'x')
        {
            swap(Map[x][0],Map[x][1]);
            y = 1;
        }
    }
    else
    {
        if(check(x,0) && check(x+1,0))
        {
            swap(Map[x][0],Map[x][1]);
            y = 0;
            BFS(x,y);
        }
        else if(check(x,0) && Map[x-1][0] == 'x')
        {
            swap(Map[x][0],Map[x][1]);
            y = 0;
        }
    }
 
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for(ll i = 1; i <= n; i++)
    {
        cin >> Map[i][0] >> Map[i][1];
    }
    for(ll i = n; i >= 1; i--)
    {
 
        if(Map[i][0] == 'o' && Map[i][1] == 'o')
        {
            if(check(i+1,0))
            {
                BFS(i,0);
                BFS(i,1);
            }
            else if(check(i+1,1))
            {
                BFS(i,1);
                BFS(i,0);
            }
 
        }
        else if(Map[i][0] == 'o')
        {
            BFS(i,0);
        }
        else if(Map[i][1] == 'o')
        {
            BFS(i,1);
        }
    }
    /*
    cout << endl;
    for(ll i = 1; i <= n; i++)
    {
        cout << Map[i][0] << Map[i][1] << endl;
    }
    */
 
 
    cout << ans << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值