zoukankan      html  css  js  c++  java
  • HDU4433locker【dp】

    locker

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1481    Accepted Submission(s): 654

    Problem Description
    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 4th digit down)
    Given the current state and the secret password, what is the minimum amount of steps you have to rotate the locker in order to get from current state to the secret password?
    Input
    Multiple (less than 50) cases, process to EOF.
    For each case, two strings with equal length (≤ 1000) consists of only digits are given, representing the current state and the secret password, respectively.
    Output
    For each case, output one integer, the minimum amount of steps from the current state to the secret password.
    Sample Input
    111111 222222 896521 183995
    Sample Output
    2 12
     
    Source

     大意:这个题是去年亚洲区的一个题  题意很简单:就是告诉你一个有n位数的密码锁(n<=1000),然后问最少通过多少步操作能得到正确的结果

    操作的内容是:每次可以选择连续的一个两个或者三个数字进行旋转数字从0到9然后又循环到0

    这个题还是比较好的  我觉得还是蛮有意思的

    dp[i][j][k]表示前i位已经匹配第i+1位为j 第i+2位为k的最少步数

    比如 1 1 1 1 1 1

           2 2 2 2 2 2

    dp[3][4][5] 所表示的状态就是

      0 2 2 4 5

      0 2 2 2 2 2 2 

    不难发现只要每次都把i-1的j和k枚举一遍  再将其全部转移到第i种状态之下就可以了

    转移过程中遇到两个问题

    一是如何把转以后的状态如何表示出来  一是转移的步数是多少

    对于第一个问题

    假如i - 1的dp为dp[i-1][j][k]

    那么此时前i-1位已经完全匹配  现在就是把j变成b[i]可以确定正转和反转各有多少步

    那么对于dp[i][j2][k2]   原来的k变成了现在的j2  原来的a[i + 2]变成了现在的k2

    至于转移的步数这么考虑

    只要是旋转那么一定是第i位旋转的合适的位置  假如说需要t步

    那么经过t步之后 i+1位的旋转步数t2一定<= t  而i+2位的旋转步数t2一定小于t1

    也就是说旋转t步得到的状态可以由上一种状态旋转t步得到

    也就是转移的步数就是t步

    以上这个问题就全部解决

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 
     6 const int maxn = 1010;
     7 const int INF = 1000000000;
     8 int dp[maxn][10][10];
     9 char s1[maxn], s2[maxn];
    10 int a[maxn], b[maxn];
    11 int up[10][10], dw[10][10];
    12 
    13 int main() {
    14     for(int i = 0; i < 10; i++) {
    15         for(int j = 0; j < 10; j++) {
    16             up[i][j] = j >= i ? j - i : ( 9 - i ) + ( j + 1 );
    17             dw[i][j] = i >= j ? i - j : ( i ) + ( 9 - j + 1);
    18         }
    19     }
    20     while(EOF != scanf("%s%s",s1, s2) ) {
    21         int n = strlen(s1);
    22         a[0] = b[0] = 0;
    23         for(int i = 0; i < n; i++) {
    24             a[i + 1] = s1[i] - '0';
    25             b[i + 1] = s2[i] - '0';
    26         }
    27         a[n + 1] = a[n + 2] = 0; b[n + 1] = b[n + 2] = 0;
    28         memset(dp, 0x3f, sizeof(dp));
    29         dp[0][a[1]][a[2]] = 0;
    30         for(int i = 1; i <= n; i++) {
    31             for(int j = 0; j < 10; j++) {
    32                 for(int k = 0; k < 10; k++) {
    33                     int t1 = up[j][b[i]];
    34                     for(int x = 0; x <= t1; x++) {
    35                         for(int y = 0; y <= x; y++) {
    36                             dp[i][(k + x) % 10][(a[i + 2] + y) % 10] = min(dp[i][(k + x) % 10][(a[i + 2] + y) % 10], dp[i - 1][j][k] + t1);
    37                         }
    38                     }
    39                     int t2 = dw[j][b[i]];
    40                     for(int x = 0; x <= t2; x++) {
    41                         for(int y = 0; y <= x; y++) {
    42                             dp[i][(k - x + 20) % 10][(a[i + 2] - y + 20) % 10] = min(dp[i][(k - x + 20) % 10][(a[i + 2] - y + 20) % 10], dp[i -1][j][k] + t2);
    43                         }
    44                     }
    45                 }
    46             }
    47         }
    48         int ans = INF;
    49         for(int i = 0; i < 10; i++) {
    50             for(int j = 0; j < 10; j++) {
    51                 ans = min(ans, dp[n][i][j]);
    52             }
    53         } 
    54         printf("%d
    ", ans);
    55     }
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    设计模式-11-代理模式
    设计模式-10-装饰者
    设计模式-9-组合
    设计模式-8-适配器
    设计模式-7-原型模式
    设计模式-6-建造者
    设计模式-5-单例模式
    u-boot-1.1.6 设置新分区支持设备树
    u-boot-2014.10移植(8)重定位,支持NAND启动
    u-boot-2014.10移植(7)修改环境变量的存储位置
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/4111458.html
Copyright © 2011-2022 走看看