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


    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≤104, kn) 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】:
     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<string.h>
     4 
     5 using namespace std;
     6 
     7 #define N 110
     8 #define NN 10010
     9 
    10 char str[N];
    11 int mod[N][N],ans[N],num[N],f[N][NN];
    12 int k,len;
    13 
    14 int dfs(int pos,int m,int cnt)
    15 {
    16     int i,j;
    17     if(m==0)    return 1;  //当余数为0时,表示已经找到,返回1
    18     if(pos<0||cnt<=f[pos][m]||cnt==0)   return 0;
    19 
    20     //从前面最高位开始,从小到大遍历,保证得到的ans最小
    21     for(i=pos;i>=0;i--)
    22     {
    23         for(j=0;j<num[i];j++)
    24         {
    25             if(i==len-1&&j==0)  continue;
    26             ans[i] = j;
    27             int res = (m-(mod[i][num[i]]-mod[i][j])+k)%k; //注意+k防止出现负数
    28             if(dfs(i-1,res,cnt-1))    return 1;  //进入下一层搜索
    29         }
    30         ans[i] = num[i];  //还原ans
    31     }
    32 
    33     //从后面最低位开始,从小到大遍历,保证得到的ans最小
    34     for(i=0;i<=pos;i++)
    35     {
    36         for(j=num[i]+1;j<10;j++)
    37         {
    38             if(i==len-1&&j==0)  continue;
    39             ans[i] = j;
    40             int res = (m+(mod[i][j]-mod[i][num[i]]))%k;
    41             if(dfs(i-1,res,cnt-1))    return 1;
    42         }
    43         ans[i] = num[i];  //还原
    44     }
    45     f[pos][m] = cnt;
    46   //  cout<<pos<<" "<<m<<" "<<cnt<<endl;
    47     return 0;
    48 }
    49 
    50 int main()
    51 {
    52     while(~scanf("%s",str))
    53     {
    54         int i,j;
    55         scanf("%d",&k);
    56         memset(f,0,sizeof(int)*(k+1));
    57         len = strlen(str);
    58         for(i=0;i<10;i++)   mod[0][i]=i%k;
    59         for(i=1;i<len;i++)
    60         {
    61             for(j=0;j<10;j++)
    62             {
    63                 mod[i][j] = (mod[i-1][j]*10)%k;     //mod[i][j]:  j*(10^i) 对 K 的取余 值
    64             }
    65         }
    66         int m=0;
    67         for(i=0;i<len;i++)
    68         {
    69             ans[i]=num[i]=str[len-1-i]-'0';
    70             m = (m + mod[i][ans[i]])%k;   //获得str除以k的余数m
    71         }
    72         for(i=1;i<=len;i++)  if(dfs(len-1,m,i))    break;
    73         for(i=len-1;i>=0;i--)   printf("%d",ans[i]);
    74         putchar(10);
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    vs运行代码版本不一致删除缓存
    spring framework 各版本源码下载地址
    类型初始值设定项引发异常
    datagridview 点击列标题排序
    软媒魔方u盘装系统
    sql中exists,not exists的用法
    java web第一个Servlet程序
    《ASP.NET 本质论》HttpApplication的处理管道 ,HttpMoudle,HttpHandler
    如何正确设置 Informix GLS 及 CSDK 语言环境
    Linux网络流量控制工具—Netem
  • 原文地址:https://www.cnblogs.com/crazyapple/p/3225514.html
Copyright © 2020-2023  润新知