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. c/c++指针基础使用

    #include <iostream> #include <string> using namespace std; int main() { "; "; ...

  2. CSS——选择器

    css选择器 css选择器可分为:标签(元素)选择器,ID选择器,类选择器,属性选择器,后代选择器,子代选择器,相邻兄弟选择器和兄弟选择器.... 标签选择器: //E{attr:value;attr ...

  3. 深入理解计算机系统第二版习题解答CSAPP 2.18

    将32位补码表示的数转换为10进制数. 32位补码 十进制 0x1b8 0x14 0xFFFFFE58 -424 0xFFFFFE74 -396 0x44 0xFFFFFEC8 -312 0x10 0 ...

  4. Centos7 安装mongodb3.2.9 过程

    1:wget --no-check-certificate  https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.2.9.tg ...

  5. WPF_X命名空间

    x名称空间映射的是http://schemas.microsoft.com/winfx/2006/xaml,也称为"XAML名称空间"

  6. 关于Eclipse Modeling Framework 实现模型驱动开发,第一部分

    ======================================EMF第二篇文章========================= 用 Eclipse Modeling Framework ...

  7. [记录] javascript 对象中使用setTimeout

    参考:Javascript对象中关于setTimeout和setInterval的this介绍 使用最后一个方法终于弄好了,简直了,在对象中使用setTimeout原来是这样的 做的是分钟倒计时,倒数 ...

  8. SqlBulkCopy 数据批量操作使用的类

    private void SqlBulkCopyByDataTable(string connectionString,string TableName,DataTable dt) { using ( ...

  9. Android Metro风格的Launcher开发系列第一篇

    前言:从毕业到现在已经三年多了,回忆一下这三年基本上没有写过博客,总是觉得忙,没时间写,也觉得写博客没什么大用.但是看到很多大牛们都在写博客,分享自己的东西,所以嘛本着向大牛看齐,分享第一,记录第二的 ...

  10. ###Linux基础 - 2

    点击查看Evernote原文. #@author: gr #@date: 2014-10-13 #@email: forgerui@gmail.com 一.Linux基础命令2 mount: 挂载U盘 ...