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. 求教jsp 问题,能在一台电脑上运行,不能在另外一台上运行?

    package com.mvc; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.se ...

  2. [转]c#.NET和VB.NET语法的比较

    本文转自:http://www.cnblogs.com/lify0407/archive/2007/08/01/838589.html c#.NET和VB.NET语法的比较   VB.NET C# C ...

  3. JAVA8永久代

    在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普 ...

  4. 【转】BUG敏感度的培养

    在我们刚踏入软件测试行业时,不管你是专业的.非专业的,培训出来的还是未培训的.刚进公司时你看着身边的同时报的Bug很多并且大都是严重程度高,自己也很想提高一下,想要提高自己的bug敏感度,建议从下面几 ...

  5. ASP判断文件地址是否有效

    <% Response.Write("<head><style><!--span{ font-size: 9pt }--></style> ...

  6. SQL Server 2012 内存管理 (memory management) 改进

    SQL Server 2012 的内存管理和以前的版本相比,有以下的一些变化. 一.内存分配器的变化 SQL Server 2012以前的版本,比如SQL Server 2008 R2等, 有sing ...

  7. Android logcat使用

    Android logcat使用 1. Android日志说明 当Android系统运行的时候,会搜集所有的系统信息. logcat是Android系统的一个命令行工具,主要用来查看和过滤日志信息. ...

  8. 关于Asp.Net Forms身份认证

    Asp.Net管道式的构建个我们提供了通过IHttpMoudle来订阅管线事件来达到干预HTTP请求的目的,Asp.Net的身份认证正是通过此种方式来对请求来执行身份认证的,这篇文章仅仅谈论Forms ...

  9. C#中常用修饰符

    1.存取修饰符 public:(公有的)存取不受限制 protected:(受保护的)只有包含该成员的类以及派生类可以存取  private:(私有的)只有包含该成员的类可以使用 2.类修饰符 abs ...

  10. ajax跨域请求的解决方案

    一直打算改造一下自己传统做网站的形式. 我是.Net程序员,含辛茹苦数年也没混出个什么名堂. 最近微信比较火, 由于现在大环境的影响和以前工作的总结和经验,我打算自己写一个数据,UI松耦合的比较新潮的 ...