http://poj.org/problem?id=3373

Changing Digits
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 2719   Accepted: 863

Description

Given two positive integers n and k, you are asked to generate a new integer, say m, by changing some (maybe none) digits of n, such that the following properties holds:

  1. m contains no leading zeros and has the same length as n (We consider zero itself a one-digit integer without leading zeros.)
  2. m is divisible by k
  3. among all numbers satisfying properties 1 and 2, m would be the one with least number of digits different from n
  4. among all numbers satisfying properties 1, 2 and 3, m would be the smallest one

Input

There are multiple test cases for the input. Each test case consists of two lines, which contains n(1≤n≤10100) and k(1≤k≤104kn) for each line. Both n and k will not contain leading zeros.

Output

Output one line for each test case containing the desired number m.

Sample Input

2
2
619103
3219

Sample Output

2
119103

Source

 
[思路]:
看了别人的解题报告才写出来。一开始不知道怎么搜,没思路。
我们知道:假设k的位数是D,那么改变n的最后D+1位,能得到k+1的顺序数,由鸽巣原理,这k+1个数中至少有1个数能被k整除。所以,至多替换n的D+1位,肯定能找到结果。(1) 先搜比n小的数 
(2)再搜比n的大的数 ,这样就能保证只要搜出结果来了,就一定是最小值。
(3) 改变替换的个数 。直接这样搜,会TLE。
进行剪枝,增加一数组f[110][10010];
f[i][j] = c 表示  i 位置,当前余数为 j 时,剩余替换次数为 c ,index 在区间[0,c-1]时都不成立。
 
【code】:
 #include<iostream>
#include<stdio.h>
#include<string.h> using namespace std; #define N 110
#define NN 10010 char str[N];
int mod[N][N],ans[N],num[N],f[N][NN];
int k,len; int dfs(int pos,int m,int cnt)
{
int i,j;
if(m==) return ; //当余数为0时,表示已经找到,返回1
if(pos<||cnt<=f[pos][m]||cnt==) return ; //从前面最高位开始,从小到大遍历,保证得到的ans最小
for(i=pos;i>=;i--)
{
for(j=;j<num[i];j++)
{
if(i==len-&&j==) continue;
ans[i] = j;
int res = (m-(mod[i][num[i]]-mod[i][j])+k)%k; //注意+k防止出现负数
if(dfs(i-,res,cnt-)) return ; //进入下一层搜索
}
ans[i] = num[i]; //还原ans
} //从后面最低位开始,从小到大遍历,保证得到的ans最小
for(i=;i<=pos;i++)
{
for(j=num[i]+;j<;j++)
{
if(i==len-&&j==) continue;
ans[i] = j;
int res = (m+(mod[i][j]-mod[i][num[i]]))%k;
if(dfs(i-,res,cnt-)) return ;
}
ans[i] = num[i]; //还原
}
f[pos][m] = cnt;
// cout<<pos<<" "<<m<<" "<<cnt<<endl;
return ;
} int main()
{
while(~scanf("%s",str))
{
int i,j;
scanf("%d",&k);
memset(f,,sizeof(int)*(k+));
len = strlen(str);
for(i=;i<;i++) mod[][i]=i%k;
for(i=;i<len;i++)
{
for(j=;j<;j++)
{
mod[i][j] = (mod[i-][j]*)%k; //mod[i][j]: j*(10^i) 对 K 的取余 值
}
}
int m=;
for(i=;i<len;i++)
{
ans[i]=num[i]=str[len--i]-'';
m = (m + mod[i][ans[i]])%k; //获得str除以k的余数m
}
for(i=;i<=len;i++) if(dfs(len-,m,i)) break;
for(i=len-;i>=;i--) printf("%d",ans[i]);
putchar();
}
return ;
}

poj 3373 Changing Digits (DFS + 记忆化剪枝+鸽巢原理思想)的更多相关文章

  1. POJ 3373 Changing Digits 好蛋疼的DP

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

  2. POJ 3373 Changing Digits

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

  3. POJ 3373 Changing Digits 记忆化搜索

    这道题我是看了别人的题解才做出来的.题意和题解分析见原文http://blog.csdn.net/lyy289065406/article/details/6698787 这里写一下自己对题目的理解. ...

  4. POJ 3373 Changing Digits(DP)

    题目链接 记录路径的DP,看的别人的思路.自己写的也不好,时间居然2000+,中间的取余可以打个表,优化一下. 写的各种错,导致wa很多次,写了一下午,自己构造数据,终于发现了最后一个bug. dp[ ...

  5. POJ 1191 棋盘分割 【DFS记忆化搜索经典】

    题目传送门:http://poj.org/problem?id=1191 棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submission ...

  6. poj 3249(bfs+dp或者记忆化搜索)

    题目链接:http://poj.org/problem?id=3249 思路:dp[i]表示到点i的最大收益,初始化为-inf,然后从入度为0点开始bfs就可以了,一开始一直TLE,然后优化了好久才4 ...

  7. 不要62 hdu 2089 dfs记忆化搜索

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意: 给你两个数作为一个闭区间的端点,求出该区间中不包含数字4和62的数的个数 思路: 数位dp中 ...

  8. dfs+记忆化搜索,求任意两点之间的最长路径

    C.Coolest Ski Route 题意:n个点,m条边组成的有向图,求任意两点之间的最长路径 dfs记忆化搜索 #include<iostream> #include<stri ...

  9. POJ 3370. Halloween treats 抽屉原理 / 鸽巢原理

    Halloween treats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7644   Accepted: 2798 ...

随机推荐

  1. 有关<action android:name="android.intent.action.DELETE" />

    今天看一个病毒样本时遇到了这个Action,位于一个Activity节点下 通过真机测试与导师指导发现,这个Action的作用就相当于把其所在的应用加入到了“系统卸载程序”列表,当你卸载系统中的任一应 ...

  2. HTTPS协议学习总结

    目录 一:什么是HTTPS协议?二:客户端与服务端如何建立HTTPS协议连接?三:证书.加密协议.信息摘要.签名算法概念解释与关系梳理四:低版本操作系统作为客户端发送HTTPS失败分析五:参考资料   ...

  3. FontAwesome 奥森图标的学习

    很早之前,就看到大家在使用代码做出很漂亮的图标,但是觉得需求不是很大,所以就没有看,但是技多不压身,这次有时间来学习下. FontAwesome官方网站 1,下载文件包 里面有两个文件夹,css 和 ...

  4. oracle两种导出导入方式,即imp与impdp之比较

    尽管使用了很多次impexp及impdpexpdp但是使用起来还是会遇到很多问题,现总结如下: 应用:将一个用户的所有表结构及索引,触发器,过程,函数等导入到另一用户里 imp/exp 导出用户表结构 ...

  5. js中的FileSystemObject使用(FSO)

    Set fso = Server.CreateObject("Scripting.FileSystemObject") 定义FSO对象 fso.CreateFolder(Serve ...

  6. oracle里面的时间转字符串to_char(),字符串转时间to_date(),以及substr和instr的使用。

    工作中编写过的一条语句 select * from Bt_Holiday where to_char(Setting_DATE,'YYYY')=Substr('2015-03-00',1,4) AND ...

  7. DOM方式解析XML文件实例

    books.XML文件: <?xml version="1.0" encoding="utf-8"?><bookstore>    &l ...

  8. win10 删除资源管理器中的6个文件夹

    细心的朋友会发现,在Win10此电脑(计算机)中,除了我们最熟悉的磁盘外,还新增了视频.图片.文档.下载.音乐.桌面这6个文件夹.不少网友举觉得这6个文件夹其实并没什么用,想要去除删掉.那么Win10 ...

  9. 数据库不能用delete---index空间不足

    只有0702表是这样的情况,0101表可以使用like和between and

  10. msSQL数据库备份还原小结

    MSSQL自带了一个样例数据库pubs,就拿这个举例好了. 首先,来一次完全备份.对于数据量很大的数据库,这样的操作当然很费时间.所以我们采用每天凌晨4点一次完全备份,每个小时一个差异备份,每分钟一次 ...