题意:有一个n(n<=1000)位密码锁,每位都是0~9,可以循环旋转。每次可以让1~3个相邻数字同时往上或者往下转一格。输入初始状态和终止状态(长度不超过1000),问最少要转几次。

分析:

1、从左往右依次使各个数字与终止状态相同。

2、dp[cur][x1][x2][x3]表示当前研究数字为第cur位,x1为a[cur],x2为a[cur + 1],x3为a[cur + 2],在当前状态下,使所有数字变成终止状态的最小旋转次数。

3、研究第cur位时,第cur+1位和第cur+2位也可以随之一起转,枚举当前所有的旋转情况,并分别讨论向上和向下旋转两种情况。

#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) ((a < b) ? a : b)
#define Max(a, b) ((a < b) ? b : a)
const double eps = 1e-8;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 1000 + 10;
const int MAXT = 10000 + 10;
using namespace std;
char aa[MAXN], bb[MAXN];
int a[MAXN], b[MAXN];
int dp[MAXN][15][15][15];
int len;
int getUpStep(int st, int et){//向上翻转的步数,向上转数字变大
return (et - st + 10) % 10;
}
int getDownStep(int st, int et){
return (st - et + 10) % 10;
}
int upNowpos(int st, int length){
return (st + length) % 10;
}
int downNowpos(int st, int length){//从st向下翻转length步变成的数字
return (st - length + 10) % 10;
}
int dfs(int cur, int x1, int x2, int x3){
if(dp[cur][x1][x2][x3] != -1) return dp[cur][x1][x2][x3];
if(cur == len) return 0;
int ans = INT_INF;
int upstep = getUpStep(x1, b[cur]), downstep = getDownStep(x1, b[cur]);
for(int i = 0; i <= upstep; ++i){//枚举第cur+1位可以跟着第cur位一起向上旋转的步数
for(int j = 0; j <= i; ++j){//枚举第cur+2位可以跟着第cur位和第cur+1位一起向上旋转的步数
ans = Min(ans, dfs(cur + 1, upNowpos(x2, i), upNowpos(x3, j), a[cur + 3]) + upstep);
}
}
for(int i = 0; i <= downstep; ++i){//向下转
for(int j = 0; j <= i; ++j){
ans = Min(ans, dfs(cur + 1, downNowpos(x2, i), downNowpos(x3, j), a[cur + 3]) + downstep);
}
}
return dp[cur][x1][x2][x3] = ans;
}
int main(){
while(scanf("%s%s", aa, bb) == 2){
memset(dp, -1, sizeof dp);
len = strlen(aa);
for(int i = 0; i < len; ++i) a[i] = aa[i] - '0';
for(int i = 0; i < len; ++i) b[i] = bb[i] - '0';
a[len] = a[len + 1] = a[len + 2] = 0;
b[len] = b[len + 1] = b[len + 2] = 0;
printf("%d\n", dfs(0, a[0], a[1], a[2]));
}
return 0;
}

  

UVA - 1631 Locker(密码锁)(dp---记忆化搜索)的更多相关文章

  1. UVa 10599【lis dp,记忆化搜索】

    UVa 10599 题意: 给出r*c的网格,其中有些格子里面有垃圾,机器人从左上角移动到右下角,只能向右或向下移动.问机器人能清扫最多多少个含有垃圾的格子,有多少中方案,输出其中一种方案的格子编号. ...

  2. UVa 1252 (状压DP + 记忆化搜索) Twenty Questions

    题意: 有n个长为m的各不相同的二进制数(允许存在前导0),别人已经事先想好n个数中的一个数W,你要猜出这个数. 每次只可以询问该数的第K为是否为1. 问采用最优询问策略,则最少需要询问多少次能保证猜 ...

  3. UVa 10817 (状压DP + 记忆化搜索) Headmaster's Headache

    题意: 一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师. 每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两 ...

  4. uva 10123 - No Tipping dp 记忆化搜索

    这题的题意是 在双脚天平上有N块东西,依次从上面取走一些,最后使得这个天平保持平衡! 解题: 逆着来依次放入,如果可行那就可以,记得得有木板自身的重量. /********************** ...

  5. 状压DP+记忆化搜索 UVA 1252 Twenty Questions

    题目传送门 /* 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 若 ...

  6. 【bzoj5123】[Lydsy12月赛]线段树的匹配 树形dp+记忆化搜索

    题目描述 求一棵 $[1,n]$ 的线段树的最大匹配数目与方案数. $n\le 10^{18}$ 题解 树形dp+记忆化搜索 设 $f[l][r]$ 表示根节点为 $[l,r]$ 的线段树,匹配选择根 ...

  7. 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索

    [题意]给定无向图,聪聪和可可各自位于一点,可可每单位时间随机向周围走一步或停留,聪聪每单位时间追两步(先走),问追到可可的期望时间.n<=1000. [算法]期望DP+记忆化搜索 [题解]首先 ...

  8. [题解](树形dp/记忆化搜索)luogu_P1040_加分二叉树

    树形dp/记忆化搜索 首先可以看出树形dp,因为第一个问题并不需要知道子树的样子, 然而第二个输出前序遍历,必须知道每个子树的根节点,需要在树形dp过程中记录,递归输出 那么如何求最大加分树——根据中 ...

  9. poj1664 dp记忆化搜索

    http://poj.org/problem?id=1664 Description 把M个相同的苹果放在N个相同的盘子里,同意有的盘子空着不放,问共同拥有多少种不同的分法?(用K表示)5.1.1和1 ...

随机推荐

  1. 阿里云安装mysql,初始化密码修改

    阿里云服务器,centos7, rpm包安装MySQL,初始化了个奇葩密码 登陆不上, 修改配置文件/etc/my.cnf,在[mysqld]下面添加一行代码:skip-grant-tables se ...

  2. flutter如何使用配置文件pubspec.yaml(位于项目根目录)来管理第三方依赖包

    官方文档 在软件开发中,很多时候有一些公共的库或SDK可能会被很多项目用到,因此,将这些代码单独抽到一个独立模块,然后哪个项目需要使用时再直接集成这个模块,便可大大提高开发效率.很多编程语言或开发工具 ...

  3. 开发自己的 chart【转】

    Kubernetes 给我们提供了大量官方 chart,不过要部署微服务应用,还是需要开发自己的 chart,下面就来实践这个主题. 创建 chart 执行 helm create mychart 的 ...

  4. dubbo-admin的安装使用

    dubbo-admin下载地址:https://github.com/apache/incubator-dubbo/releases 可以直接下载到linux上 wget https://github ...

  5. 冰蝎动态二进制加密WebShell特征分析

    概述 冰蝎一款新型加密网站管理客户端,在实际的渗透测试过程中有非常不错的效果,能绕过目前市场上的大部分WAF.探针设备.本文将通过在虚拟环境中使用冰蝎,通过wireshark抓取冰蝎通信流量,结合平时 ...

  6. HashMap之Hash碰撞源码解析

    转自:https://blog.csdn.net/luo_da/article/details/77507315 https://www.cnblogs.com/tongxuping/p/827619 ...

  7. UCENTER同步登录工作原理和配置要点

    ucenter的同步登录原理: 1)Ucenter是和uc_client同步的.每个PHP应用,加入了UCENTER后,都会在主目录下有个UC_CLIENT目录.这个目录里,都有一个client.PH ...

  8. mysql DDL语言

  9. 吴裕雄--天生自然java开发常用类库学习笔记:System类

    public class SystemDemo01{ public static void main(String args[]){ long startTime = System.currentTi ...

  10. B. Misha and Changing Handles

    B. Misha and Changing Handles time limit per test 1 second memory limit per test 256 megabytes input ...