CodeChef WPROB(数组辅助+暴力求解)

这边有中文的题目:
https://codechef_shared.s3.amazonaws.com/download/translated/LTIME21/mandarin/WPROB.pdf

解析:

因为每次移动木块,只有该木块移动其他的木块的相应位置不会发生改变,利用贪心的思想,移动的次数为当前位置前面不同颜色木块的次数。
因为最终的情况只可能有6种。所以枚举这6种情况,计算出最小的移动步数。
那么移动步数怎么计算呢?
比如说我要变成rgb
r移动的次数 = 在 第一个 r前面有多少个 gb + 第二个 r前面 有多少个 gb …..
第二次 找 b
b移动的次数 = 第一个 g前面有多少 b + 第二个 g前面有多少 b…..
移动成rgb的次数 = r移动的次数+b移动的次数

注意:这题的答案超过了int要用long long初始化最小值是要开成很大的数字,long long范围的最大值。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
char s[N];
ll dp[N][3];
int color[3], hash[256];
int len;
void init() {
    for(int i = 0; i < 3; i++)
        color[i] = i;
}
ll solve() {
    ll cnt = 0;
    for(int i = 1; i <= len; i++) {
        if(color[0] == hash[s[i]]) {
            cnt += (dp[i][color[1]] + dp[i][color[2]]);
        }
    }
    for(int i = 1; i <= len; i++) {
        if(color[1] == hash[s[i]]) {
            cnt += dp[i][color[2]];
        }
    }
    return cnt;
}
int main() {
    hash['r'] = 0; hash['g'] = 1; hash['b'] = 2;

    int T;
    scanf("%d", &T);
    while(T--) {
        init();

        scanf("%s", s+1);
        len = strlen(s+1);

        for(int j = 0; j < 3; j++) dp[0][j] = 0;
        for(int i = 1; i <= len; i++) {
            for(int j = 0; j < 3; j++)
                dp[i][j] = dp[i-1][j];
            if(s[i] == 'r') dp[i][0]++;
            else if(s[i] == 'g') dp[i][1]++;
            else if(s[i] == 'b') dp[i][2]++;
        }
        ll MIN = solve();
        while(next_permutation(color, color + 3)) {
            MIN = min(MIN, solve());
        }
        printf("%lld\n", MIN);
    }
    return 0;
}

你可能感兴趣的:(CodeChef WPROB(数组辅助+暴力求解))