C 小球下落

想要代码量少,思维量一定要大。
这个题可以用爆搜,但我太菜了写不出来 ,比赛时写了个只得了30分。赛后看了眼大佬们的代码,才发现是真的巧妙。

首先核心思想是贪心。反向输入图形,把第行当作第行,现在的目标就是尽可能的去让球去填满上面的空。但是,有三种情况是会封死路的

  • xx
  • .x
    x.
  • x.
    .x

所以要分区。所以现在问题就转化成了,让球去尽量往上填这一分区的空

先给出代码

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
int n , r , f , Q[N << 1];
long long ans=0;
char a[N][5];

int main()
{
    scanf("%d", &n);
    for(int i = n; i >= 1;i--) scanf("%s", a[i]);
    for(int i = 1; i <= n;i++)
    {
        if(a[i][0] != 'x') Q[r++] = i;
        if(a[i][1] != 'x') Q[r++] = i;
        if(a[i][0] == 'o') ans += i - Q[f++];
        if(a[i][1] == 'o') ans += i - Q[f++];
        if((a[i][0]=='x'&&a[i][1]=='x')||(a[i][0]=='x'&&a[i+1][1]=='x')||(a[i+1][0]=='x'&&a[i][1]=='x')) r = f = 0;
    }
    printf("%lld\n", ans);
    return 0;
}

一一解释变量。

  • 数组下标是递增的,代表目前除了x的个数; 数组的值代表这个不是x的字符是第几行的。
    顺着下来,上去的球就也相当于点了。

  • 就是下标。

      if(a[i][0] != 'x') Q[r++] = i;
      if(a[i][1] != 'x') Q[r++] = i;
  • 为全部空位(包括点和已经上去的球)已被球占用了的个数,也同样作为的下标。

      if(a[i][0] == 'o') ans += i - Q[f++];
      if(a[i][1] == 'o') ans += i - Q[f++];

    加上当前行减去目前存在空位最上面的行继续自增。

  • 最后,就是当出现三种拦路的情况,直接让 都清即可。相当于就是开辟了个新的分区,啥都清了。