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 */  
代码快来拿
原文地址:https://www.cnblogs.com/dfzg/p/7125079.html