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位已经全部转到目标态了。   那么转移也就很显然了, 计算出a上转和下转的次数, 然后b、c位的数字有选择的转多少次。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 1000000000;
const int maxn = 1000 + 10;
int T,n,m,kase=0,d[maxn][15][15][15],vis[maxn][15][15][15];
char s1[maxn], s2[maxn];
int dp(int i, int a, int b, int c) {
    int& ans = d[i][a][b][c];
    if(i >= n) return 0;
    if(vis[i][a][b][c] == kase) return ans;
    vis[i][a][b][c] = kase;
    int t = s2[i] - '0';
    ans = INF;
    if(a < t) {
        int xia = t - a;
        for(int j=0;j<=xia;j++) {
            for(int k=0;k<=j;k++) {
                int v = (b + j)%10, u = (c + k)%10;
                ans = min(ans, dp(i+1, v, u, s1[i+3]-'0')+xia);
            }
        }
        int shang = 10 - xia;
        for(int j=0;j<=shang;j++) {
            for(int k=0;k<=j;k++) {
                int v = (b - j + 10)%10, u = (c - k + 10)%10;
                ans = min(ans, dp(i+1, v, u, s1[i+3]-'0')+shang);
            }
        }
    }
    else {
        int shang = a - t;
        for(int j=0;j<=shang;j++) {
            for(int k=0;k<=j;k++) {
                int v = (b - j + 10)%10, u = (c - k + 10)%10;
                ans = min(ans, dp(i+1, v, u, s1[i+3]-'0')+shang);
            }
        }
        int xia = 10 - shang;
        for(int j=0;j<=xia;j++) {
            for(int k=0;k<=j;k++) {
                int v = (b + j)%10, u = (c + k)%10;
                ans = min(ans, dp(i+1, v, u, s1[i+3]-'0')+xia);
            }
        }
    }
    return ans;
}
int main() {
    while(~scanf("%s%s",s1,s2)) {
        ++kase;
        n = strlen(s1);
        for(int i=n;i<=n+1;i++) {
            s1[i] = s2[i] = '0';
        }
        s1[n+4] = s2[n+4] = '\0';
        printf("%d\n",dp(0,s1[0]-'0',s1[1]-'0',s1[2]-'0'));
    }
    return 0;
}
时间: 2024-10-13 21:01:22

HDU 4433 locker(DP)( UVA 1631 - Locker)的相关文章

hdu 2147 kiki&#39;s game(DP(SG)打表找规律)

题意: n*m的棋盘,一枚硬币右上角,每人每次可将硬币移向三个方向之一(一格单位):左边,下边,左下边. 无法移动硬币的人负. 给出n和m,问,先手胜还是后手胜. 数据范围: n, m (0<n,m<=2000) 思路: dp[i][j]=0,说明从(i,j)这个点到时左下角先手败.dp[i][j]=1则先手胜. 然后记忆搜.但是记忆搜会超时. 搜完把整张表打出来,发现规律了,,,,然后,,,代码剩几行了. 代码: ///打表观察 /* int f[2005][2005]; int go(in

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie)

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie) ACM 题目地址: UVALive 3942 - Remember the Word 题意: 给一些单词,然后给一个长的单词,问有几种方法能组成这个大单词,单词可以重复用. 分析: DP[i]=sum{DP[j} (i<j<len),从后往前求. 本来用数组Trie写得爽爽的,1A了. 发现2s多,不能忍! 然后用指针Trie写了一遍,各种出错,整个人都不好了... 研究了一遍别人代码,发现快

hdu 1087 Super Jumping! Jumping! Jumping!(dp:上升子序列最大和)

Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 24824    Accepted Submission(s): 10961 Problem Description Nowadays, a kind of chess game called "Super Jumping!

hdu 1087 Super Jumping! Jumping! Jumping!(dp 最长上升子序列和)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1087 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 欢迎光临天资小屋:http://user.qzone.qq.com/593830943

HDU 4359 Easy Tree DP?(是dp但并不是tree dp + 组合计数)

HDU 4359 题意:定义Bear Tree为一颗二叉树,这种二叉树每个结点有一个权值,范围在2^0~2^n-1,并且每个值只用一次,对于每个结点,如果同时存在左右子树,那么左子树的权值和要小于右子树的权值和.求点数为N,层次为D的Bear Tree的数量. 思路: 2^0 + 2^1 + ... + 2^n < 2^(n+1) 根据这个性质,我们可以得出权值最大节点必须在右子树上,并且只要同时存在左右子树,则将权值最大节点放在右子树上就一定符合条件. 所以我们用dp[i][j]表示点数为i且

POJ1417:True Liars(DP+带权并查集)

True Liars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16338    Accepted Submission(s): 5724 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 Description: After having drifted about in a

poj 1742 Coins(dp之多重背包+多次优化)

Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact pri

FJNU 1176 汪老司机(DP or 建图+最短路)

1196: 汪老司机 Time Limit: 1000 MS         Memory Limit: 257792 KB 64-bit interger IO format: %lld        Java class name: Main Prev Submit  Discuss Next 汪老司机是实验室出了名的老司机,早在大一就拿到了驾照,每年的暑假他都会带家人开车出游,今年的暑假也不例外,汪老司机今年准备带家人去平潭游玩,汪老司机的家离平潭有两条路,每条路都存在n个路段,两条路的n

zzuli1985(dp/水dfs郑轻比赛)

再一次感受到dp的威力 1985: 即将到来的新生赛 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 112  Solved: 28 SubmitStatusWeb Board Description 新生赛马上就要到来了.为了举办这次比赛,学校也是大费苦心.由于时间紧迫,要准备的事情太多,人员安排也是很伤脑子.身为一个聪明的acmer,这点小事对你来说应该是So easy! 距离新生赛开始剩余100个小时,现在还剩余m项任务.每个任务都有开始时间,