UVALive - 7263 Today Is a Rainy Day (BFS预处理)

Today Is a Rainy Day(传送门)

题意

给定两个字符串 s1 s2 ,将 s2 变为 s1 ,变化操作有以下两种:

  1. 将一个位置上的数字变为另外一个数字
  2. 将一种数字变为另外一种数

求最小代价

解题思路

做题的时候仔细的思考过,先进行第二种变化比先第一种优(俺无法证明,有些疑惑),当然当时基本能才猜出是这样处理,接下来则是如何进行处理?
对于第二种变化,我们可以用 BFS 进行处理,求出将匹配状态变为不匹配状态最少需要多少步。
说的匹配状态变为不匹配状态的意思如下:

{1,2,3,4,5,6}>{1,2,3,4,5,6}

这个只需要 0 步,将第一种与第二种匹配
{1,2,3,4,5,6}>{2,2,3,4,5,6}

这个则需要 1 <script type="math/tex" id="MathJax-Element-2652">1</script>步,将第一种与第二种匹配

求完种类变化的,接下则是一个一个变化的,直接进行计算经过种类变化后需要第一种变化多少次才能变为最终的结果即可

总的来说,这道题还是非常经典,不仅对于猜想还是去直接证明,当然直接证明不会,很尴尬,但是猜想出先进行完第二种然后进行第一种还是比较简单的,难点基本就是用BFS处理出种类变化的效果即可,比较有意思

代码

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

typedef long long LL;
const int MAXN = 5e4 + 5;
const int MAXM = 1e2 + 20;
const int INF = 0x3f3f3f3f;
const int mod = 1e8 + 7;
char s1[MAXM], s2[MAXM];
char l[MAXM], g[MAXM][MAXM];
int dp[MAXN];

int idx(int c[]) {
    int ret = 0;
    for(int i = 0; i < 6; i ++) {
        ret = ret * 6 + c[i];
    }
    return ret;
}

void rdix(int s, int c[]) {
    for(int i = 5; i >= 0; i --) {
        c[i] = s % 6;
        s /= 6;
    }
}

void BFS() {
    memset(dp, 0x3f, sizeof(dp));
    int c[6] = {0, 1, 2, 3, 4, 5}, s = idx(c), tmp[6];
    queue<int>Q;
    dp[s] = 0;
    Q.push(s);
    while(!Q.empty()) {
        int s = Q.front();
        Q.pop();
        rdix(s, c);
        for(int i = 0; i < 6; i ++) {
            for(int j = 0; j < 6; j ++) {
                memcpy(tmp, c, sizeof(tmp));
                for(int k = 0; k < 6; k ++) {
                    if(tmp[k] == i) {
                        tmp[k] = j;
                    }
                }
                int ns = idx(tmp);
                if(dp[ns] > dp[s] + 1) {
                    dp[ns] = dp[s] + 1;
                    Q.push(ns);
                }
            }
        }
    }
}


int main() {
    BFS();
    while(~scanf("%s%s", s1, s2)) {
        int len = strlen(s1);
        memset(l, 0, sizeof(l));
        memset(g, 0, sizeof(g));
        for(int i = 0; i < len; i ++) {
            int c1 = s1[i] - '1', c2 = s2[i] - '1';
            l[c2] ++;
            g[c2][c1] ++;
        }
        int tmp[6];
        int mins = INF;
        for(int i = 0; i < MAXN; i ++) {
            int sum = dp[i];
            rdix(i, tmp);
            for(int j = 0; j < 6; j ++) {
                sum += l[j] - g[j][tmp[j]];
            }
            mins = min(mins, sum);
        }
        printf("%d\n", mins);
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值