zoukankan      html  css  js  c++  java
  • codeforces1202B You Are Given a Decimal String... 记忆化搜索或Floyd最短路算法

    网址:http://codeforces.com/problemset/problem/1202/B

    题意:

    这个题真的挺绕的,草(中日双语),就是给出一串序列,然后你可以往里面填数,使得填数后的序列可以被$x-y$计数器输出。$x-y$计数器的工作方式是:初始是$0$,每一步加上$x$或者加上$y$,然后输出对$10$取余的数。输出$0<x,y<10$的$x-y$计数器下需要添加的字符数最小值,若无法满足输出$-1$。

    题解:

    草,比赛时靠着网上的资料一步步写出的记忆化搜索的方法,想不出正解是转化成最短路。

    一、dfs记忆化搜索

    对于不断对$10$取余的序列,不超过$10$轮就会出现相同的数字,因此,$dfs$最多只有$10$轮,遇到重复的数字时,如果搜索的层数小于原来保存的层数,则更新,大于等于则返回保证了搜索结果的层数都是最小值。然后字符串的一个字符到下一个字符相当于状态转移,直接读取保存下来的状态即可。

    AC代码:$(600ms)$

    #include <bits/stdc++.h>
    using namespace std;
    int dp[15][15][15],res[15][15];
    char str[2000005];
    int x,y;
    void dfs(int div,bool mode,int cur)
    {
        if(!mode)
        {
            cur=(cur+x)%10;
            if(dp[x][y][cur]!=-1)
                if(div>=dp[x][y][cur])
                    return;
            dp[x][y][cur]=div;
            dfs(div+1,0,cur);
            dfs(div+1,1,cur);
        }
        else
        {
            cur=(cur+y)%10;
            if(dp[x][y][cur]!=-1)
                if(div>=dp[x][y][cur])
                    return;
            dp[x][y][cur]=div;
            dfs(div+1,0,cur);
            dfs(div+1,1,cur);
        }
    }
    void init()
    {
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<10;++i)
            for(int j=0;j<10;++j)
            {
                x=i,y=j;
                dfs(0,0,0);
                dfs(0,1,0);
            }
    }
    int cal(int x,int y,int len)
    {
        if(len==1)
            return 0;
        int ans=0;
        for(int i=1;i<len;++i)
        {
            int tmp;
            int dis=str[i]-str[i-1];
            while(dis<0)
                dis+=10;
            tmp=dp[x][y][dis];
            if(tmp==-1)
                return -1;
            else
                ans+=tmp;
        }
        return ans;
    }
    int main()
    {
        init();
        scanf("%s",str);
        int len=strlen(str);
        for(int i=0;i<10;++i)
            for(int j=0;j<10;++j)
                res[i][j]=cal(i,j,len);
        for(int i=0;i<10;++i)
            for(int j=0;j<10;++j)
                printf("%d%c",res[i][j],(j==9?'
    ':' '));
        return 0;
    }
    

     二、floyd算法

    状态转移$x->y$相当于是建立一条$x$到$y$的边权为$1$的有向边,最小值相当于是$str[i-1]->str[i],(0<i<len(str))$的最短路,所以直接建图,邻接矩阵存,对每个情况跑一遍$floyd$算法即可。

    AC代码:$(200ms)$

    #include <bits/stdc++.h>
    using namespace std;
    int dp[15][15],len;
    char str[2000005];
    const int inf=0x3f3f3f3f;
    int solve(int x,int y)
    {
        memset(dp,inf,sizeof(dp));
        for(int i=0;i<10;++i)
            dp[i][(i+x)%10]=dp[i][(i+y)%10]=1;
        for(int k=0;k<10;++k)
            for(int i=0;i<10;++i)
                for(int j=0;j<10;++j)
                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
        int ans=0;
        for(int i=1;i<len;++i)
        {
            if(dp[str[i-1]-'0'][str[i]-'0']>=inf)
                return -1;
            ans+=dp[str[i-1]-'0'][str[i]-'0']-1;
        }
        return ans;
    }
    int main()
    {
        scanf("%s",str);
        len=strlen(str);
        for(int i=0;i<10;++i)
            for(int j=0;j<10;++j)
                printf("%d%c",solve(i,j),(j==9?'
    ':' '));
        return 0;
    }
    
  • 相关阅读:
    Hadoop 2.7.1 源代码目录结构分析
    Jit
    java性能分析工具
    最近一个dish项目的建设思考
    mysql的ACID的理解
    实践中积累沟通组织经验
    系统性能--磁盘/网卡
    系统性能--CPU
    调停者模式的批斗
    channel和Stream的对比
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/11330649.html
Copyright © 2011-2022 走看看