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("\n");
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 */  

代码快来拿

时间: 2024-08-08 21:54:20

poj3373--Changing Digits(DFS+剪枝///记忆化)的相关文章

poj 1088 动态规划+dfs(记忆化搜索)

滑雪 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个 区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6

从DFS到记忆化DFS

从DFS到记忆化DFS到动态规划 什么是动态规划? 动态规划(Dynamic Programming)是通过组合子问题的解来解决问题的.动态规划是用于求解包含重叠子问题的最优化问题的方法.其基本思想是,将原问题分解为相似的子问题.在求解的过程中通过子问题的解求出原问题的解. 动态规划的分类: 1.       线性规划:拦截导弹,合唱队形,挖地雷等. 2.       区域规划:石子合并,加分二叉树,统计单词个数等. 3.       树形动规:贪吃的九头龙,二分查找树,聚会的欢乐等. 4.  

poj 1088 滑雪 DP(dfs的记忆化搜索)

题目地址:http://poj.org/problem?id=1088 题目大意:给你一个m*n的矩阵 如果其中一个点高于另一个点 那么就可以从高点向下滑 直到没有可以下滑的时候 就得到一条下滑路径 求最大的下滑路径 分析:因为只能从高峰滑到低峰,无后效性,所以每个点都可以找到自己的最长下滑距离(只与自己高度有关).记忆每个点的最长下滑距离,当有另一个点的下滑路径遇到这个点的时候,直接加上这个点的最长下滑距离. dp递推式是,dp[x][y] = max(dp[x][y],dp[x+1][y]+

Dfs/Bfs/记忆化搜索问题 | 问题集合

写在前面 动归和搜索似乎我打得特憋懒. 可能是因为搜索打的太少了??? 然后之前做过的一些题我就不再写了,比如填涂颜色/海战啥的? 然后每一题打两种解法(:Dfs/Bfs 前提是在题目里两种都能A P1596 湖计数 题目描述 Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <=

pku1088 dfs+dp记忆化搜索

滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 88861   Accepted: 33344 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17

HDOJ 题目1088 滑雪(DFS,记忆化)

滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 80448   Accepted: 29995 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17

dfs之记忆化搜索(字符串匹配,位置相对变)

题目链接:http://acm.hdu.ed #include<iostream> #include<string.h> #include<stdio.h> using namespace std; char a[210],b[210],c[500]; int mark[210][210]; int n; int dfs(int i,int j,int k) { if(mark[i][j]) return mark[i][j];//能够匹配 if(c[k]=='\0')

[ACM] FZU 2092 收集水晶 (DFS,记忆化搜索)

Problem Description shadow来到一片神奇的土地,这片土地上不时会出现一些有价值的水晶,shadow想要收集一些水晶带回去,但是这项任务太繁杂了,于是shadow让自己的影子脱离自己并成为一个助手来帮助自己收集这些水晶. shadow把这片土地划分成n*m个小方格,某些格子会存在一些shadow和他的影子都无法穿越的障碍,比如巨石.树木.野兽等.shadow预先探测到了水晶出现的时间.位置以及它们的价值,但这些水晶的存在就如昙花一现般短暂,若在出现后1秒内没有收集到,它便将

NYOJ skiing(DFS+记忆化搜索)

skiing 时间限制:3000 ms  |  内存限制:65535 KB 描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点