• poj3373--Changing Digits(DFS+剪枝///记忆化)


    题目链接:点击打开链接

    题目大意:给出一个n和一个k 求m

    要求1、m要和n相同的位数

    要求2、m要整除k

    要求3、如果1和2满足,那么m要和n有尽量少的不同位

    要求4、如果1、2、3满足,要使m尽量的小

    简单的一个深搜,但是直接被要求吓蒙,,,,,

    要求1和2直接可以在搜索时判断,要求3可以在深搜时给出可以改变的位数(有0到len(n)),而要求4需要控制在搜索是要从小的开始搜,即从100000到999999,因为在深搜之前就控制了可以改变的次数,所以在搜索时不用担心要求3,只要使要求1要求2满足就可以,那么搜到的第一个就是最小的。

    注意剪枝:

    1、在每一次变化后都要直接计算出余数,当余数为0时,返回1,而不是一定要搜到最后一位。

    mod[i][j] = (j*10^i)%k

    2、flag[i][j]当搜到第i位余数为j时,没有找到结果的(修改位数),当以后遇到修改位数<=flag[i][j]时直接返回0。

     1 #include <cstdio>  
     2 #include <cstring>  
     3 #include <algorithm>  
     4 
     5 using namespace std;  
     6 
     7 char str[110];  
     8 int k,len,a[110];  
     9 int mod[110][10];  
    10 int flag[110][11000];  
    11 void init(){  
    12     for(int j=0;j<10;j++)  
    13         mod[0][j]=j%k;  
    14     for(int i=1;i<110;i++)  
    15         for(int j=0;j<10;j++)  
    16             mod[i][j]=mod[i-1][j]*10%k;  
    17 }  
    18 
    19 int dfs(int num,int pos,int s){  
    20     if(s == 0) return 1;  
    21     if(num == 0 || pos == -1) return 0;  
    22     if(num <= flag[pos][s]) return 0;  
    23     int temp ;  
    24     for(int i=0;i<=9;i++){  
    25         if(pos == len-1 && i == 0 ) continue;  
    26         if(i<a[pos]){  
    27             temp=a[pos]-i;  
    28             a[pos]=i;  
    29             if(dfs(num-1,pos-1,(s-mod[pos][temp]+k)%k)) return 1;  
    30             a[pos]+=temp;  
    31         }  
    32         else if(i == a[pos]){  
    33             if(dfs(num,pos-1,s)) return 1;  
    34         }  
    35         else{  
    36             temp=i-a[pos];  
    37             a[pos]=i;  
    38             if(dfs(num-1,pos-1,(s+mod[pos][temp])%k)) return 1;  
    39             a[pos]-=temp;  
    40         }  
    41     }  
    42     flag[pos][s]=max(flag[pos][s],num);  
    43     return 0;  
    44 }  
    45 
    46 int main(){  
    47     int i,j,s,temp;  
    48     while(scanf("%s %d",str,&k)!=EOF){  
    49         memset(flag,-1,sizeof(flag));  
    50         len=strlen(str);  
    51         for(i=len-1;i>=0;i--){  
    52             a[len-1-i]=str[i]-'0' ;  
    53         }  
    54         init();  
    55         for(i=s=temp=0;i<len;i++){  
    56             s=(mod[i][a[i]]+temp)%k ;  
    57             temp=s;  
    58         }  
    59         for(i=0;i<=len;i++){  
    60             if(dfs(i,len-1,s)) break;  
    61         }  
    62         for(i=len-1;i>=0;i--)  
    63             printf("%d",a[i]);  
    64         printf("
    ");  
    65     }  
    66     return 0;  
    67 }  
    68   
    69 /* 
    70 535064 
    71 9084 
    72 535956 
    73  
    74  
    75 19169 15724 
    76 15724 
    77  
    78 3902 153 
    79 3978 
    80 */  
    代码快来拿
  • 相关阅读:
    算法分析(3)——冒泡排序真的慢吗?
    算法分析(2)——大O和大Θ
    算法分析(1)——数据的影响和函数的增长
    递归的逻辑(5)——米诺斯的迷宫
    递归的逻辑(4)——递归与分形
    李洪强和你一起学习前端之(9)规避脱标,CSS可见性,滑动门案例
    iOS应用管理(优化)
    iOS开发-应用管理
    iOS开发-Tom猫
    iOS 10.3.3 更新背后的故事
  • 原文地址:https://www.cnblogs.com/dfzg/p/7125079.html
Copyright © 2020-2023  润新知