poj 3373 Changing Digits(打表 + dfs + 剪枝 )
题意:给出两个数N和K,让你改变N中的某些数,找到一个数M,是的M%k== 0 ,并且找到的M要尽可能小。
思路:呃,其实我真的不擅长搜索,特别是搜,不过这题还是学到了很多东西。首先是一种大整数取模的方法。其实是参考着这篇解题报告学会的,
http://blog.csdn.net/lyy289065406/article/details/6698787 对于这题,他讲的很详细,我也是参考他的思路,所以就不说了。
代码:

#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 ; }
分类:
DFS
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现