这道题我是看了别人的题解才做出来的。题意和题解分析见原文http://blog.csdn.net/lyy289065406/article/details/6698787

这里写一下自己对题目的理解。

1. 根据k的最大范围直接搜索n最后5位的方法是错误的,因为它并不能保证所求结果为最小。因为题目要求最后结果m要尽量小,而改变n的高位能够得到更小的值。k<n的限制条件表明解必然存在,而我们搜索的最大可修改位数应该和n的位数len相等。

2. 最终结果m必须满足:最高位非0且与n位数相同 (m若等于0不视为最高位为0),m能被k整除。在此基础上,还有两个条件,它们的优先级为:m与n对应位置上的数不相等的个数尽量少 > m尽量小。即最终得到的结果不一定是最小的,但一定是与n对应位置数字不相等个数最少的。这也决定了本题dfs的写法。

3. 面对大量大数取模运算,利用mod[i][j]预处理(10^i)*j模k的值,节省了大量时间。这样在dfs的过程中,改变某一位后的m%k的值也能计算出来了。搜索时为了求得的结果最小,先从m<n开始搜,然后再搜m>n。

前者有res = (m_modk - (mod[i][n[i]] - mod[i][j]) + k) % k;

后者有res = (m_modk + (mod[i][j] - mod[i][n[i]]) + k) % k;

4. flag数组的引入是为了剪枝。如果当搜索区间为[0, pos]且此时m模k为m_modk时,如果最多修改restnum位不能成功,则修改次数少于restnum时更不可能成功,因此就不用搜索下去了。flag[pos][m_modk]始终维护上述情况无法成功的最大restnum。

我的代码

 #include<stdio.h>
#include<string.h>
#define maxn 103
#define mk 10003
int len, k, n[maxn], mod[maxn][];
int m[maxn], flag[maxn][mk];
char num[maxn];
void init_mod()//mod[i][j]表示(10^i)*j模k的值
{
for (int i = ; i <= ; i++)
mod[][i] = i % k;
for (int i = ; i < len; i++)
for (int j = ; j <= ; j++)
mod[i][j] = (mod[i-][j] * ) % k;
}
int dfs(int pos,int restnum,int m_modk)
{
if (!m_modk) return ;
if (!restnum || pos < ) return ;
if (restnum <= flag[pos][m_modk]) return ;//剪枝
for (int i = pos; i > -; i--)//搜索比n小的数,要尽可能小,则从高位开始
for (int j = ; j < n[i]; j++)
{
if (i == len - && !j) continue;
int res = (m_modk - (mod[i][n[i]] - mod[i][j]) + k) % k;
m[i] = j;
if (dfs(i - , restnum - , res))
return ;
m[i] = n[i];
}
for (int i = ; i <= pos; i++)//搜索比n大的数,要尽可能小,则从低位开始
for (int j = n[i] + ; j < ; j++)
{
int res = (m_modk + (mod[i][j] - mod[i][n[i]]) + k) % k;
m[i] = j;
if (dfs(i - , restnum - , res))
return ;
m[i] = n[i];
}
flag[pos][m_modk] = restnum;//能运行到这里说明搜索失败,更新剪枝数值
return ;
}
int main()
{
while (~scanf("%s%d", num, &k))
{
int n_modk = ;
len = strlen(num);
init_mod();
for (int i = ; i < len; i++)//将num反序存入整型数组
{
n[i] = num[len--i] - '';
m[i] = n[i];
n_modk = (n_modk + mod[i][ n[i] ]) % k;//计算n % k
}
memset(flag, , sizeof(flag));
int ok = ;
for (int i = ; i <= len; i++)//从小到大枚举可以修改的位数
if (dfs(len - , i, n_modk))
break;
for (int i = len - ; i > -; i--)
printf("%d", m[i]);
printf("\n");
}
return ;
}

POJ 3373 Changing Digits 记忆化搜索的更多相关文章

  1. poj 3373 Changing Digits (DFS + 记忆化剪枝+鸽巢原理思想)

    http://poj.org/problem?id=3373 Changing Digits Time Limit: 3000MS   Memory Limit: 65536K Total Submi ...

  2. POJ 1088 滑雪(记忆化搜索)

    滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 92384   Accepted: 34948 Description ...

  3. POJ 1088 滑雪 DFS 记忆化搜索

    http://poj.org/problem?id=1088 校运会放假继续来水一发^ ^ 不过又要各种复习,功课拉下了许多 QAQ. 还有呀,就是昨天被一个学姐教育了一番,太感谢了,嘻嘻^ ^ 好了 ...

  4. POJ 1088 滑雪【记忆化搜索】

    题意:给出一个二维矩阵,要求从其中的一点出发,并且当前点的值总是比下一点的值大,求最长路径 记忆化搜索,首先将d数组初始化为0,该点能够到达的路径长度保存在d数组中,同时把因为路径是非负的,所以如果已 ...

  5. poj 1088 滑雪_记忆化搜索

    题意:略 直接用记忆化搜索就行了 #include<cstdio> #include<iostream> using namespace std; int n,m; int m ...

  6. POJ 3373 Changing Digits 好蛋疼的DP

    一開始写的高位往低位递推,发现这样有些时候保证不了第四条要求.于是又開始写高位往低位的记忆化搜索,又发现传參什么的蛋疼的要死.然后又发现高位開始的记忆化搜索就是从低位往高位的递推呀,遂过之. dp[i ...

  7. POJ 3176-Cow Bowling(DP||记忆化搜索)

    Cow Bowling Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14210   Accepted: 9432 Desc ...

  8. POJ 3373 Changing Digits

    题目大意: 给出一个数n,求m,使得m的长度和n相等.能被k整除.有多个数符合条件输出与n在每位数字上改变次数最小的.改变次数同样的输出大小最小的.  共同拥有两种解法:DP解法,记忆化搜索的算法. ...

  9. HDU 1501 & POJ 2192 Zipper(dp记忆化搜索)

    题意:给定三个串,问c串是否能由a,b串任意组合在一起组成,但注意a,b串任意组合需要保证a,b原串的顺序 例如ab,cd可组成acbd,但不能组成adcb. 分析:对字符串上的dp还是不敏感啊,虽然 ...

随机推荐

  1. Spring---浅谈IOC

    概念 IOC(Inversion of Control 控制反转)是spring的核心,贯穿始终.所谓IOC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系. 传统 ...

  2. Dsamain

    TechNet 库 Windows Server Windows Server 2008 R2 und Windows Server 2008 Windows Server 命令.参考和工具 Comm ...

  3. LeetCode——Problem1:two sum

    早就想刷LeetCode了,但一直在拖,新学期开学,开始刷算法. 我准备从Python和C++两种语言刷.一方面我想做机器学习,以后用Python会比较多,联系一下.另一方面C++或者C语言更接近底层 ...

  4. sqlserver2008透明书库加密

    /*Title:TDE加密Author:浪客Environment:Windows Server 2008 Enterprise + SQL Server 2008 EnterpriseDescrip ...

  5. pb8.0 mssqlserver 新建数据库连接问题

    将ntwdblib.DLL复制到Sybase\Shared\PowerBuilder目录下 unable to load the requested database interface,无法创建数据 ...

  6. 学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用利用条件运算符的嵌套来完成此题:C表示。

    # -*- coding: utf8 -*- # Author:wxq #python 2.7 #题目:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用利用条件运算符 ...

  7. jquery版tab切换效果

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  8. 使用BootStrap网格布局进行一次演示

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. [HAOI2011][bzoj2301] Problem b [莫比乌斯反演+容斥原理+分块前缀和优化]

    题面: 传送门 有洛谷就尽量放洛谷链接呗,界面友好一点 思路: 和HDU1695比较像,但是这一回有50000组数据,直接莫比乌斯反演慢慢加的话会T 先解决一个前置问题:怎么处理a,c不是1的情况? ...

  10. pat Public Bike Management (30)

    There is a public bike service in Hangzhou City which provides great convenience to the tourists fro ...