『hihocoder 1251』Today Is a Rainy Day (2015ICPC北京C题)

题目链接:http://hihocoder.com/problemset/problem/1251
转载声明:http://blog.csdn.net/lyc1635566ty/article/details/53074067

题意:
给你2个数字串,每个数字串的数字只会有{1,2,3,4,5,6},6个数字组成,然后给你2个操作
1)将一个数字变成另外的数字.
2 ) 讲一类相同的数字变成另外的数字.
问最少次数可以变成目的串…

分析:
今天补了一下2015北京赛题.
这简直烧智商啊,我开始感觉就是bfs,我也没往其他方向去想,可是我根本不会做.最主要难处理的是那个一堆变的状态,我想到的状态转换要用 110^36 的空间 来保留我走过的位置,我记得我们也做过一个类似的bfs 就是那个 素数路径到另一个目的数字的状态,我总想着这是一个模型,一直往那个地方想,可是我的状态好难定啊…然后果断godie,看看题解,这是个银牌题啊…真难…

这是我第一次搞的bfs,大神的思想就不一样,首先,我们想,明显先操作了操作2,再来用操作1的方式最好.可能有人觉得我可能先做操作1,然后我再来个操作2,再操作1.可是你仔细想想,要是这样的话状态更乱,而且之前转得可能也是白费的.
我是这样想的,既然认为先做操作1,再做操作2,
莫非就产生两种情况.
操作1把原来的数字改对了,然后你通过操作2填完整序列
例如 22222 21222
        11111 11111 这时就血亏了.明明一次就行了

又或者说说,把他改错…
例如 21222 22222
        11111 11111 这样子又明明可能多了一次,为什么? 如果他本身是错的,改过来还是错,那么这还是2次,如果他本身是对的,你却要硬生生改错,这就白白浪费一次.对吧?

反正牵一发而动全身的东西就应该先做,这道题目的转弯角度很大.转不过弯来GG,能转过弯来就不是问题了.还是能力问题啊.

反正原来的状态 他是1就是1 123456
然后从 123456 转化成 其他数字,
顶多就 6^6次种,然后我们就可以确定 原来有的数字怎么转了…

然后再暴力操作1即可得答案.

代码:

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=666666+10;;

int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }

int vis[maxn];
queue<int>gg;
int ansn[maxn];
int anst[maxn];
int num;
char s1[maxn];
char s2[maxn];

void init()
{
    for(int i=1;i<maxn;i++){vis[i]=maxn;}
    num=1;
    ansn[1]=123456;
    anst[1]=0;
    gg.push(123456);
    vis[123456]=0;

    while(!gg.empty())
    {
        int t1=gg.front();
        int p=t1;
        gg.pop();
        int b[10];
        for(int j=6;j>=1;j--) {
            b[j]=p%10;
            p/=10;
        }
        for(int i=1;i<=6;i++) { //当前状态中的i变成j
            for(int j=1;j<=6;j++) {
                if(i==j) continue;
                int tt=0;
                for(int k=1;k<=6;k++) {
                    if(b[k]==i) {
                        tt=tt*10+j;
                    }
                    else {
                        tt=tt*10+b[k];
                    }
                }
                if(vis[t1]+1<vis[tt]) {
                    vis[tt]=vis[t1]+1;
                    gg.push(tt);
                    num++;
                    ansn[num]=tt;
                    anst[num]=vis[tt];
                }

            }
        }
    }
}
int main()
{
    init();
    while(scanf("%s%s",s2,s1)!=EOF)
    {
        int minx=maxn;
        for(int i=1;i<=num;i++)
        {
            int tot=anst[i];
            int a[10];
            int p=ansn[i];
            for(int j=6;j>=1;j--)
            {
                a[j]=p%10;
                p/=10;
            }


            for(int i=0;s1[i]!='\0';i++)
            {
                if(s1[i]==1+'0')
                {
                    if((a[1]+'0')!=s2[i])tot++;
                    continue;
                }
                if(s1[i]==2+'0')
                {
                    if((a[2]+'0')!=s2[i])tot++;
                    continue;
                }
                if(s1[i]==3+'0')
                {
                    if((a[3]+'0')!=s2[i])tot++;
                    continue;
                }
                if(s1[i]==4+'0')
                {
                    if((a[4]+'0')!=s2[i])tot++;
                    continue;
                }
                if(s1[i]==5+'0')
                {
                    if((a[5]+'0')!=s2[i])tot++;
                    continue;
                }
                if(s1[i]==6+'0')
                {
                    if((a[6]+'0')!=s2[i])tot++;
                    continue;
                }
            }
            minx=min(minx,tot);
        }
        printf("%d\n",minx);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值