• poj 3373 Changing Digits(打表 + dfs + 剪枝 )


    题意:给出两个数N和K,让你改变N中的某些数,找到一个数M,是的M%k== 0 ,并且找到的M要尽可能小。

    思路:呃,其实我真的不擅长搜索,特别是搜,不过这题还是学到了很多东西。首先是一种大整数取模的方法。其实是参考着这篇解题报告学会的,

    http://blog.csdn.net/lyy289065406/article/details/6698787 对于这题,他讲的很详细,我也是参考他的思路,所以就不说了。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <queue>
    #include <map>
    #include <math.h>
    #define  N 110
    #define  M 14
    using namespace std;
    
    int mod[N][M] , n[N] , m[N] ;
    int k , n_mod , len ;
    char str[N] ;
    int** vis ;
    
    void Init( int len , int k )
    {
        n_mod = 0 ;
        vis = new int*[len+1] ;
        for ( i = 0 ; i <= len ; i++ )
        {
            vis[i] = new int[k] ;
            memset( vis[i] , 0 , sizeof( int ) * k );
        }
        
        return  ;
    }
    
    void Mod_Table( int len )
    {
        int i , j ;
    
        for ( i = 0 ; i <= 9 ; i++ )
        mod[0][i] = i % k ;
    
        for ( i = 1 ; i < len ; i++ )
        for ( j = 0 ; j <= 9 ; j++ )
        mod[i][j] = ( mod[i-1][j] * 10 ) % k ;
    
        return ;
    }
    
    void Cal_n_Mod( int len )
    {
        int i ;
    
        for ( i = 0 ; i < len ; i++ )
        {
            n[i] = m[i] = str[len - i - 1] - '0' ;
            n_mod = ( n_mod + mod[i][n[i]] ) % k ;
        }
    
        return  ;
    }
    
    int dfs( int pos , int res , int m_mod)
    {
        if ( m_mod == 0 )//如果m_mod为0的话说明找到了最小的m
        return 1 ;
    
        if( pos < 0 || res == 0 )//如果改变的长度为0或改变的位置为0 的话,返回false
        return 0 ;
    
        if ( res <= vis[pos][m_mod] )//剪枝,如果改变的长度已经小于在这个位置得到这个余数的话,直接返回
        return 0 ;
    
        int i , j ;
        for ( i = pos ; i >= 0 ; i-- )//因为n已经被逆序存放了,若要找的最小的m,应该从高位开始找。
        {
            for ( j = 0 ; j < n[i] ; j++ )//高位的变得越小越好,所以,从0开始
            {
                if ( i == len - 1 && j == 0 )
                continue ;
    
                int x_mod = ( m_mod - ( mod[i][m[i]] - mod[i][j] ) + k ) % k ;
                int tem = m[i] ;
                m[i] = j ;
    
                if ( dfs ( i - 1 , res - 1 , x_mod ))
                return 1 ;
    
                m[i] = tem ;
            }
        }
    
        for( i = 0 ; i <= pos ; i++  )//同理,找大于N的数,从低位开始找
        {
            for ( j = n[i] + 1 ; j <= 9 ; j++ )//并且从小的数字开始替换。这样可以保证找到的事最小的M
            {
                if ( i == len - 1  && j == 0 )
                continue ;
    
                int x_mod = ( m_mod + ( mod[i][j] - mod[i][m[i]] )) % k ;
                int tem = m[i] ;
                m[i] = j ;
    
                if ( dfs ( i - 1 , res - 1 , x_mod ))
                return 1 ;
    
                m[i] = tem ;
            }
        }
    
        vis[pos][m_mod] = res ;
        return 0 ;
    }
    
    int main()
    {
        int i ;
        while( cin>>str>>k )
        {
            len = strlen( str );
            Init( len , k );//初始化数组vis
            Mod_Table( len );//打表,用来求 m % k ;
            Cal_n_Mod( len );//计算 n % k ;
            
            //dfs 深搜
            for ( i = 1 ; i <= len ; i++ )
            if ( dfs ( len - 1 , i , n_mod ))
            break;
    
            for ( i = 0 ; i < len ; i++ )
            printf ( "%d" , m[len-i-1] );
            printf ( "\n" );
    
            delete []vis ;
        }
        return 0 ;
    }
  • 相关阅读:
    Java中关系操作符==的学习以及与equals的对比
    关于alibaba.fastjson的使用
    给有C或C++基础的Python入门 :Python Crash Course 1
    快速幂基本模板
    断言封装及应用(有难度)
    断言封装之key检查及kv实战示例
    正则取值及断言实战示例
    关联实现下-jsonpath取值(有难度!!耗时长)
    关联实现上-jsonpath取值
    requests顺序执行实现
  • 原文地址:https://www.cnblogs.com/misty1/p/2633390.html
Copyright © 2020-2023  润新知