Educational Codeforces Round 128 (Rated for Div. 2) E. Moving Chips

题目链接:E. Moving Chips

题意
只有 * 和 . 的2行n列的图,每次可以将任意一个 *移动一格,当两个 *相遇
时将合并为一个,问最少需要多少不能将所有 *合并为一个

思路:
贪心,对于每一排,看离他最近的前面的*在哪,用last1last2 表示

对于每个点,我们可以贪心的把后面的 * 先移到他这,然后再让他往前移,也可以让后面的 * 在他移的路径路径上跟他合并

如果是前者,更新完这个点后,lasti更新为i,如果是后者,last1 last2都更新为i,而如何决定为那种情况就看更新这个点前last1 last2 的关系

如果之前 last1==last2,肯定就是第一种情况,因为同时更新last1last2得多走一步,也只是让后面的点最多少走一步,而如果后面的点没少走,就不是最优解

如果之前last1!=last2last1 last2 中最大值是和当前*在一行,也是第一种情况,原因一样

反之就同时更新last1 last2 ,这样保证该点移动步数最小的情况下,后面的点移动步数也最小

有个特殊情况就是同一列两个都是*,这样就先把他们合并,再往前走,因为合并后在哪行总步数一样,所以只用考虑 last1 last2 最大值就好

Code:

#include <bits/stdc++.h>
#define debug freopen("_in.txt", "r", stdin);
// #define debug freopen("_in.txt", "r", stdin), freopen("_out.txt", "w", stdout);
typedef long long ll;
typedef unsigned long long ull;
typedef struct Node *bintree;
using namespace std;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll maxn = 1e6 + 10;
const ll maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const double pi = acos(-1);
const double eps = 1e-8;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

ll T;
ll n, m, maxx;
char str[10][maxn];

void solve()
{
    
    
    scanf("%lld", &n);
    for (ll i = 1; i <= 2; i++)
    {
    
    
        scanf("%s", str[i] + 1);
    }
    ll cnt = 0, flag = 0, last1 = -1, last2 = -1;
    for (ll i = 1; i <= n; i++)
    {
    
    
        if (str[1][i] == '*' && str[2][i] == '*')
        {
    
    
            if (!flag)
            {
    
    
                cnt++;
                flag = 1;
                last1 = last2 = i;
            }
            else
            {
    
    
                ll maxx = max(last1, last2);
                cnt++;
                cnt += i - maxx;
                last1 = last2 = i;
            }
        }
        else if (str[1][i] == '*')
        {
    
    
            if(!flag)
            {
    
    
                flag=1;
                last1=i;
                continue;
            }
            ll maxx = max(last1, last2);
            ll minn = min(last1, last2);
            if (maxx == minn)
            {
    
    
                cnt += i - maxx;
                last1 = i;
            }
            else
            {
    
    
                if (maxx == last1)
                {
    
    
                    cnt += i - maxx;
                    last1 = i;
                }
                else
                {
    
    
                    cnt += i - maxx;
                    cnt++;
                    last1 = i;
                    last2 = i;
                }
            }
        }
        else if (str[2][i] == '*')
        {
    
    
            if(!flag)
            {
    
    
                flag=1;
                last2=i;
                continue;
            }
            ll maxx = max(last1, last2);
            ll minn = min(last1, last2);
            if (maxx == minn)
            {
    
    
                cnt += i - maxx;
                last2 = i;
            }
            else
            {
    
    
                if (maxx == last2)
                {
    
    
                    cnt += i - maxx;
                    last2 = i;
                }
                else
                {
    
    
                    cnt += i - maxx;
                    cnt++;
                    last1 = i;
                    last2 = i;
                }
            }
        }
    }
    printf("%lld\n", cnt);
}

int main()
{
    
    
    // debug;
    // T = 1;
    scanf("%lld", &T);
    while (T--)
    {
    
    
        solve();
    }
}

Tips:
语言表达能力有限,欢迎各位聚聚提出建议、问题,有不懂的地方也欢迎提问,我会尽力解答

猜你喜欢

转载自blog.csdn.net/m0_51270992/article/details/124763220