HDU 4433 locker(三维dp)

这题不太好想啊。。。。我以为是记忆化搜索但是感觉最后的状态不好转移啊。别人都是用三维dp写的,感觉很巧啊。

binshen写的:http://www.cnblogs.com/kuangbin/archive/2012/10/27/2742672.html

这题的意思就相当于是一个数字密码锁。

每次可以正向或者反向旋转连续的1-3个数字。求从现在状态转到目标状态需要的最少步数。

题目给了两个长度一样的由0-9组成的字符串。就相当于每次操作可以选择连续的1-3个数字加1或者减1.这不过这个加和减是循环的。0减1到9,9加1到0.

一看就是DP。

这不过DP方程不好想,也不好表示状态。

dp[i][x][y]表示处理到第i个,后面两个数字是x,y,把前i位转正确需要的最少步数。

计算dp[i][x][y]时,前i-2位是题目给的现在状态的值,第i-1位是x,第i位是y,就是把前i位转正确。

要把dp[i]的状态转移到dp[i-1]去。

把第i位从x转到目标态b[i]去,就可以把状态转移了。

和第i位相关的转动有三种:一是单转第i位,二是转第i位和第i-1位,三是转第i位、第i-1位和第i-2位。

根据三种可以确定 dp[i-1][xx][yy]中的xx,yy;

转动分为正转和反转。

如果第i位是正转,转正确需要d1步。

那么第i-1和第i-2位正转的不是是小于等于d1的。而且i-2的步数小于等于i-1。

如果第i位是正转,转正确需要d2步。

那么第i-1和第i-2位正转的不是是小于等于d2的。而且i-2的步数小于等于i-1。

这样DP的时候i从1到n转移过去。

处理dp[i]的时候,dp[1~(n-1)][0~9][0~9]都是已知的。就很容易确定dp[i][0~9][0~9]的最小值了。

locker

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1494    Accepted Submission(s): 662

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
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <time.h>
#include <stack>
#include <map>
#include <set>
#define eps 1e-8
///#define LL long long
#define LL __int64
#define INF 0x3f3f3f
#define PI 3.1415926535898
#define mod 1000000007

using namespace std;

const int maxn = 1010;

int dp[maxn][10][10];
char str1[maxn], str2[maxn];
int num1[maxn];
int num2[maxn];

int main()
{
    while(~scanf("%s %s",str1, str2))
    {
        int n = strlen(str1);
        for(int i = 0; i < n; i++)
        {
            num1[i+1] = str1[i]-'0';
            num2[i+1] = str2[i]-'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] = INF;
        dp[0][0][0] = 0;
        for(int i = 1; i <= n; i++)
        {
            for(int x = 0; x < 10; x++)
            {
                if(i <= 1 && x > 0) break;
                for(int y = 0; y < 10; y++)
                {
                    int dx = (num2[i]-y+10)%10;
                    int dy = (y-num2[i]+10)%10;
                    int xx, yy;
                    if(i == 1)
                    {
                        xx = yy = 0;
                        dp[i][x][y] = min(dp[i][x][y], dp[i-1][xx][yy]+min(dx, dy));
                        continue;
                    }
                    if(i == 2)
                    {
                        xx = 0;
                        for(int j = x; j <= x+dx; j++)
                        {
                            yy = j%10;
                            dp[i][x][y] = min(dp[i][x][y], dp[i-1][xx][yy]+dx);
                        }
                        for(int j = x; j >= x-dy; j--)
                        {
                            yy = (j+10)%10;
                            dp[i][x][y] = min(dp[i][x][y], dp[i-1][xx][yy]+dy);
                        }
                        continue;
                    }
                    for(int j = 0; j <= dx; j++)
                    {
                        for(int k = j; k <= dx; k++)
                        {
                            xx = (num1[i-2]+j)%10;
                            yy = (x+k)%10;
                            dp[i][x][y] = min(dp[i][x][y], dp[i-1][xx][yy]+dx);
                        }
                    }
                    for(int j = 0; j <= dy; j++)
                    {
                        for(int k = j; k <= dy; k++)
                        {
                            xx = (num1[i-2]-j+10)%10;
                            yy = (x-k+10)%10;
                            dp[i][x][y] = min(dp[i][x][y], dp[i-1][xx][yy]+dy);
                        }
                    }
                }
            }
        }
        int x = 0;
        int y = 0;
        if(n >= 2) x = num1[n-1];
        if(n >= 1) y = num1[n];
        cout<<dp[n][x][y]<<endl;
    }
    return 0;
}
时间: 2024-10-09 04:14:11

HDU 4433 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位已经全部转到目标态了.  

HDU 4960 (水dp)

Another OCD Patient Problem Description Xiaoji is an OCD (obsessive-compulsive disorder) patient. This morning, his children played with plasticene. They broke the plasticene into N pieces, and put them in a line. Each piece has a volume Vi. Since Xi

HDU 1253 (简单三维广搜) 胜利大逃亡

奇葩!这么简单的广搜居然爆内存了,而且一直爆,一直爆,Orz 而且我也优化过了的啊,尼玛还是一直爆! 先把代码贴上睡觉去了,明天再来弄 1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <queue> 6 #include <cmath> 7 using namespace std; 8 9 struct Poin

HDU 1087 &amp;&amp; POJ 2533(DP,最长上升子序列).

~~~~ 两道题的意思差不多,HDU上是求最长上升子序列的和,而POJ上就的是其长度. 貌似还有用二分写的nlogn的算法,不过这俩题n^2就可以过嘛.. ~~~~ 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1087 http://poj.org/problem?id=2533 ~~~~ HDU1087: #include<cstdio> #include<cstring> #include<algorithm> #

hdu 2296 aC自动机+dp(得到价值最大的字符串)

Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3180    Accepted Submission(s): 1033 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a rom

hdu 2457 AC自动机+dp

DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2004    Accepted Submission(s): 1085 Problem Description Biologists finally invent techniques of repairing DNA that contains segments c

[ACM] hdu 3555 Bomb (数位DP,统计1-N中含有“49”的总数)

Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 7187 Accepted Submission(s): 2512 Problem Description The counter-terrorists found a time bomb in the dust. But this time the terrorists impro

HDU 4833 Best Financing DP

Best Financing Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 120    Accepted Submission(s): 24 Problem Description 小 A想通过合理投资银行理财产品达到收益最大化.已知小A在未来一段时间中的收入情况,描述为两个长度为n的整数数组dates和earnings,表示在

hdu 1011(树形dp)

Mark.看着吴神博客写的,还未完全懂. 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <set> 8 #include <map> 9 #include <string>