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;
    }
    
  • 相关阅读:
    Effective Java 第三版——26. 不要使用原始类型
    Effective Java 第三版——25. 将源文件限制为单个顶级类
    Effective Java 第三版——24. 优先考虑静态成员类
    Effective Java 第三版——23. 优先使用类层次而不是标签类
    Effective Java 第三版——22. 接口仅用来定义类型
    Effective Java 第三版——21. 为后代设计接口
    Effective Java 第三版——20. 接口优于抽象类
    Effective Java 第三版——19. 如果使用继承则设计,并文档说明,否则不该使用
    Effective Java 第三版——18. 组合优于继承
    Effective Java 第三版——17. 最小化可变性
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/11330649.html
Copyright © 2011-2022 走看看