UVa 1631 Locker (DP)

题意:有一个 n 位密码锁,每位都是0-9,可以循环旋转。同时可以让1-3个相邻数字进行旋转一个,给定初始状态和目状态,问你最少要转多少次。

析:很明显的一个DP题。dp[i][j][k] 表示前 i 位已经转好,并且第 i+1 位是 j ,第 i+2 位是 k,那么我们先把第 i 位转到指定位置,然后计算转多少次,

然后再考虑 i+1位和 i+2位,要旋转小于等于第 i 位的次数,这就转移完了。比较简单的一个DP,只是没有遇见过。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const LL LNF = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e3 + 5;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
char s1[maxn], s2[maxn];
int a[maxn], b[maxn];
int g[2][15][15];
LL dp[maxn][15][15];

int solve(int pre, int last, int cnt){
    return cnt ? (last+10-pre) % 10 : (pre+10-last) % 10;
}

int main(){
    for(int i = 0; i < 2; ++i)  for(int j = 0; j < 10; ++j)
        for(int k = 0; k < 10; ++k)  g[i][j][k] = i ? (j+k) % 10 : (j-k+10) % 10;

    while(scanf("%s %s", s1, s2) == 2){
        n = strlen(s1);
        for(int i = 1; i <= n; ++i) a[i] = s1[i-1] - ‘0‘, b[i] = s2[i-1] - ‘0‘;
        a[n+1] = a[n+2] = b[n+1] = b[n+2] = 0;
        for(int i = 0; i <= n; ++i) for(int j = 0; j < 10; ++j)
            for(int k = 0; k < 10; ++k) dp[i][j][k] = LNF;

        dp[0][a[1]][a[2]] = 0;
        for(int i = 1; i <= n; ++i){
            for(int r = 0; r < 2; ++r){
                for(int j = 0; j < 10; ++j){
                    for(int k = 0; k < 10; ++k){
                        int x = solve(j, b[i], r);
                        for(int ii = 0; ii <= x; ++ii){
                            for(int jj = 0; jj <= ii; ++jj){
                                dp[i][g[r][k][ii]][g[r][a[i+2]][jj]] = Min(dp[i][g[r][k][ii]][g[r][a[i+2]][jj]], dp[i-1][j][k] + x);
                            }
                        }
                    }
                }
            }
        }

        printf("%lld\n", dp[n][0][0]);
    }
    return 0;
}
时间: 2024-08-28 19:33:16

UVa 1631 Locker (DP)的相关文章

HDU 4433 locker(DP)( UVA 1631 - Locker)

题目链接:点击打开链接 题意:有一个n位密码锁,每一位都是0~9,可以循环旋转,每次可以让1~3个相邻数字同时往上或者往下旋转一格. 输入初始状态和终止状态,问最少需要转几次. 思路: 很显然是个DP题目, 由于每次可以让相邻的1~3个数字同时旋转, 所以状态的表示上就要考虑相邻3个位置. 那么可以用d[i][a][b][c]表示当前到了第i位,第i位上当前是a,i+1位是b,i+2位是c. 那么显然必须让i位上变成目标数字了, 因为接下来就转移到i+1位了,说明前i位已经全部转到目标态了.  

uva 1631

1631 Locker A password locker with N digits, each digit can be rotated to 0-9 circularly. You can rotate 1-3 consecutive digits up or down in one step. For examples: 567890 → 567901 (by rotating the last 3 digits up) 000000 → 000900 (by rotating the

uva 12723 概率dp

Dudu is a very starving possum. He currently stands in the first shelf of a fridge. This fridge iscomposed of N shelves, and each shelf has a number Qi (1 ≤ i ≤ N) of food. The top shelf, whereDudu is, is identified by the number 1, and the lowest is

uva 11133 - Eigensequence(dp)

题目链接:uva 11133 - Eigensequence 题目大意:给定一个序列a,能够确定一个序列b,要求: 1)b[1]=a[1] 2)a[j?1]<b[j]≤a[j]且b[j]a[j]?a[j?1]为整数,j>1的时候 假设对于每一个ai=bi,则称b序列为Eigensequence序列. 如今给定a1和an,问有多少个Eigensequence序列. 解题思路:dp[i][j]表示第i个数为j的情况有多少种,假设k整除k-j,dp[i+1][k]+=dp[i][j]. #inclu

uva 11367 dijkstra+dp状态压缩

题意:给出n个地点 和 每个地点的油价 ,有 m 条边 , 并给出每条边长度 .1单位汽油可以走1千米  , 油箱的容量为 c , 在初始点 s 时 , 油箱中的油为 0 , 求s 到 t 的最小花费 . 解法: 定义 状态 d[i][j] 表示到达 地点 i 且油箱中有 j 单位油时的最小 花费. 对于状态的转移时 , 有两种方法: 1.把每个点的所有状态都求出 2.不把每个点的状态都求出 , 而是一单位一单位的加油. 对于第一种方法 , 会超时 , 因为每个点的状态太多 , 但是能用的状态就

uva 10593 - Kites(dp)

题目链接:uva 10593 - Kites 题目大意:给出一个n*n的图,表示一张纸板,问有多少种方法做成风筝,风筝必须是正方形或者是菱形,并且不能有洞. 解题思路:分正方形和菱形两种情况讨论: 正方形,dp[i][j]表示以i,j为右下角的正方形 dp[i][j]=min(dp[i?1][j],dp[i][j?1]) 并且如果黄色部分也为'x'的话,dp[i][j]++ 菱形,dp[i][j]表示菱形的正下角 同样地市黄色部分如果为'x'的话,dp[i][j]++ #include <cst

uva 10237 - Bishops(dp)

克里斯·厄姆森 谷歌今天在 Code 大会上发布了新的无人驾驶汽车.该汽车看起来像是有轮子的缆车,它既没有驾驶盘,也没有刹车踏板和加速装置.Re/code 采访了谷歌无人驾驶汽车项目主管克里斯·厄姆森(Chris Urmson),期间谈及该项目革命背后的概念.产品何时上路等问题. 谷歌在过去的 5 年里改装了现成车型去试验无人驾驶技术.除了车顶的旋转激光装置外,它们看上去跟普通车没什么不同.而该公司今天发布的汽车看上去则非常怪异.它们又小又圆,配备各种小型黑色传感器(车顶也有旋转激光装置),用泡

uva 674 (入门DP, 14.07.09)

 Coin Change  Suppose there are 5 types of coins: 50-cent, 25-cent, 10-cent, 5-cent, and 1-cent. We want to make changes with these coins for a given amount of money. For example, if we have 11 cents, then we can make changes with one 10-cent coin an

uva 1534 - Taekwondo(dp+贪心)

题目连接:uva 1534 - Taekwondo 题目大意:有两组什么东西,题目背景有点忘记了,就是给出两组数,两组个数分别为n,m,要求找出min(n,m)对数,每个数最多最多选一次,使得这min(n,m)对数ai,bi,ai-bi的绝对值之和最小. 解题思路:贪心,将两组数分别排序,然后dp[i][j]表示i对,匹配到j时候的最优解. #include <cstdio> #include <cstring> #include <cmath> #include &l