题目链接

题意 : 一串数字变成另一串数字,可以单个数字转变,或者一类数字转变,问最少操作次数

分析 :

15年北京赛区的银牌题

首先有一个点需要想明白、或者猜得到

即最优的做法肯定是先做完 2 操作最后用 1 操作

2 操作单次可以改变的字符数远大于 1 操作 ( 当然这个不是证明上面的结论、只是给个灵感去猜

具体操作就是 s2 => 通过 2 操作变成中间状态 => 通过 1 操作变成 s1

对于 2 操作、与具体字符的数量无关、只和种类有关、即从一种数字变成另一种

那么就是一种映射关系、那么我们可以使用一个六位的六进制数来表示不同的状态

首先将字符集全部 -1 、即原来串是由 {1,2,3,4,5,6} 组成变成由 {0,1,2,3,4,5}组成 ( 方便进制转化 )

那么这种映射关系是什么呢?如何表示的 2 操作呢?

比如 012345 => 112345 表示将原来字符所有的 0 变成 1

012345 => 112344 表示将原来字符串所有的 0 变成 1、所有的 5 变成 4

所有对于所有的状态、可以使用 BFS 从初始状态 (012345)6 开始、将它到其他状态的花费求出来

那么就可以统计出所有 2 操作能到达的状态的最小花费了、当然六进制的状态最后要用十进制存储才方便存储

最后就是像刚刚说的那样子、先枚举中间状态(6^6个最多)、然后计算出从中间状态通过 1 操作到达目标状态的花费即可

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;

 + ;
;
 + ;
const int INF = 0x3f3f3f3f;

int to_ten(int c[])///将六进制转十进制
{
    ;
    ; i<; i++){
        ret = ret *  + c[i];
    }return ret;
}

inline void to_six(int num, int c[])///十进制转六进制(存在 c 中)
{
    ; i>=; i--){
        c[i] = num % ;
        num /= ;
    }
}

int Cost[mxState];///存储操作 2 的花费

][];///存储原本 s2 => s1 只通过 1 操作所用的花费
            ///比如 g[1][2] = 3 将 s2 的 1 变成 s1 的 2 只用 1 操作要进行 3 次

];///存储 s2 中每个数字出现的次数

char s1[maxLen], s2[maxLen];

inline void BFS()
{
    ] = {, , , , , };

    int FirState = to_ten(c);
    mem(Cost, INF);
    Cost[FirState] = ;

    queue<int> que;
    que.push(FirState);
    while(!que.empty()){
        int T = que.front(); que.pop();

        to_six(T, c);

        ; i<; i++){
            ; j<; j++){
                ];
                memcpy(tmp, c, sizeof(tmp));
                ; k<; k++)
                    if(tmp[k] == i)
                        tmp[k] = j;

                int newState = to_ten(tmp);

                ){
                    Cost[newState] = Cost[T] + ;
                    que.push(newState);
                }
            }
        }
    }
}

int main(void){__stTIME();__IOPUT();

    BFS();

    while(~scs(s1)){
        scs(s2);
        int len = strlen(s1);
        mem(cnt, );
        mem(g, );
        ; i<len; i++){
            ';
            ';
            cnt[ch2]++;
            g[ch2][ch1]++;
        }

        int ans = INF;
        ];
        ; i<mxState; i++){///枚举中间状态
            to_six(i, c);
            int cost = Cost[i];///将 s2 => 中间状态 的花费
            ; j<; j++)///进行操作 1 的花费计算
                cost += cnt[j] - g[j][c[j]];///举个例子就好理解一点、比如 s1="001" 、s2="112"、用这个例子去模拟
            ans = min(ans, cost);
        }

        printf("%d\n", ans);

    }

__enTIME();;}

void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}

hihocoder 1251 Today is a rainy day ( 15年北京 C、暴力 )的更多相关文章

  1. 暴力 hihoCoder 1251 Today Is a Rainy Day (15北京C)

    题目传送门 题意:一串数字变成另一串数字,可以单个数字转变,或者一类数字转变,问最少操作次数 分析:首先一类转换比单个转换优,先枚举找出最优的映射方案,然后将零碎的操作加上.6位6进制表示map映射, ...

  2. 【BFS】【枚举】HihoCoder - 1251 - The 2015 ACM-ICPC Asia Beijing Regional Contest - C - Today Is a Rainy Day

    题意:给你两个只由1~6组成的串,问你B串至少要经过几次操作变成A串. 一次操作要么选择一个种类的数,将其全部变成另一种类:要么选择一个数,将其变为另一个数. 可以证明,一定先进行一定数量的第一种操作 ...

  3. hihoCoder 1391 Countries【预处理+排序+优先队列】2016北京网络赛

    题目:http://hihocoder.com/problemset/problem/1391 题目大意: A和B两个国家互射导弹,每个国家都有一个防御系统,在防御系统开启的时间内可以将到达本国的导弹 ...

  4. hihocoder 微软编程之美2015 初赛 第一场 (树算法 + 暴力思想 + 搜索思想)

    题目1 : 彩色的树 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵n个节点的树,节点编号为1, 2, …, n.树中有n - 1条边,任意两个节点间恰好有一条路 ...

  5. (中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。

    "Couple Trees" are two trees, a husband tree and a wife tree. They are named because they ...

  6. hihoCoder #1831 : 80 Days-RMQ (ACM/ICPC 2018亚洲区预选赛北京赛站网络赛)

    水道题目,比赛时线段树写挫了,忘了RMQ这个东西了(捞) #1831 : 80 Days 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 80 Days is an int ...

  7. hihoCoder 1185 连通性·三(Tarjan缩点+暴力DFS)

    #1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...

  8. 苹果应用商店AppStore审核中文指南 分类: ios相关 app相关 2015-07-27 15:33 84人阅读 评论(0) 收藏

    目录 1. 条款与条件 2. 功能 3. 元数据.评级与排名 4. 位置 5. 推送通知 6. 游戏中心 7. 广告 8. 商标与商业外观 9. 媒体内容 10. 用户界面 11. 购买与货币 12. ...

  9. 【hihocoder 1628】K-Dimensional Foil(线性代数)

    hihocoder 1627 The 2017 ACM-ICPC Asia Beijing Regional Contest 北京区域赛 B.K-Dimensional Foil 题意 给定N个点的前 ...

随机推荐

  1. CSS float和position属性

    1. 浮动 CSS float属性定义了元素在水平方向的浮动.该元素从网页的正常流动(文档流)中移除,对于浮动元素后的块级元素,块级元素将会被浮动元素覆盖,并且会接着其上一个文档流中的元素,按文档流的 ...

  2. c++11 跨平台多线程demo和qt 静态链接(std::thread有join函数,设置 QMAKE_LFLAGS = -static)

    #include <stdio.h>#include <stdlib.h> #include <chrono> // std::chrono::seconds#in ...

  3. Codeforces 1244E. Minimizing Difference

    传送门 首先减的顺序是无关紧要的,那么有一个显然的贪心 每次减都减最大或者最小的,因为如果不这样操作,最大的差值不会变小 那么直接把序列排序一下然后模拟一下操作过程即可,别一次只减 $1$ 就好 #i ...

  4. winform messageBox.Show()

    MessageBox.Show(" 5 个参数...... ",     " 亮仔提示",     MessageBoxButtons.OKCancel,    ...

  5. 解决VS2005打开js,css,asp.php等文件,中文都是乱码的问题

    用记事本打开可以正常观看但是用VS2005编辑器打开JS,中文确实乱码. 解决办法:在VS 2005 的设置里面选择自动检测Utf-8:“工具”->“选项”->“文本编辑器”->“自 ...

  6. “007~ASP 0104~不允许操作”错误的解决方法(图解)

    今天测试一个Z-Blog程序的上传文件时发现总提示“ 007~ASP 0104~不允许操作 ”的错误,经过度度上各位朋友的帮忙,终于找到解决方法. 这是windows2003 server对上传文件的 ...

  7. XML转换成DataTable

    #region XML转dataset //str 是xml字符串 public static DataTable GetResultXMLToDataTable (string str,string ...

  8. 今天朋友带领去谷歌ok2eat 餐厅吃免费午餐

    中午去队友公司免费吃饭.朋友带我们去她的楼下吃,就算是googler真的也不是所有cafe都知道,感谢朋友带领.

  9. Android中如何判断内存卡是否存在

    if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { /* 得到SD卡得路 ...

  10. std::list保存大量数据时,类型即是无析构函数,该list析构时会占用大量CPU

    std::list保存大量数据时,类型即是无析构函数,该list析构时会占用大量CPU