UVA 1631 Locker(HDU 4433)(DP)
2016-07-31 20:40
465 查看
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
题意:给两个字符串A,B,每一步可以将连续的1-3个数字上调或下调一位,问将A变成B最少需要几步。
思路:调动一位只能对它的后两位有影响,从第一位开始调,第一位只能通过它自己的变化才能变成目标数字。设dp[i][j][k]表示使i位置变为目标数字,且i+1位置变为数字j,且i+2位置变为数字k,所需要的最少步数。需要注意的一个坑数据就是,000 --> 789,只需要3步,也就是说,变第i位需要固定的x步,i+1可以只变y(y<=x)步,i+2可以只变z(z<=y)步。然后变i位的时候有上调和下调两种方式。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
using namespace std;
char s1[1005],s2[1005];
int a[1010],b[1010];
int n;
int dp[1005][10][10];
int main()
{
while(scanf("%s%s",s1,s2)!=EOF)
{
n=(int)strlen(s1);
for(int i=1;i<=n;i++)
{
a[i]=s1[i-1]-'0';
b[i]=s2[i-1]-'0';
}
memset(dp,0x3f3f3f3f,sizeof(dp));
a[n+1]=b[n+1]=0;
a[n+2]=b[n+2]=0;
dp[0][a[1]][a[2]]=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<10;j++)
{
for(int k=0;k<10;k++)
{
if(dp[i-1][j][k]!=0x3f3f3f3f)
{
int x;
if(b[i]>=j) x=b[i]-j; //将第i位上调x步
else x=10+b[i]-j;
dp[i][k][a[i+2]]=min(dp[i][k][a[i+2]],dp[i-1][j][k]+abs(x));
for(int l=0;l<=x;l++)
{
int c=(k+l+20)%10;
dp[i][c][a[i+2]]=min(dp[i][c][a[i+2]],dp[i-1][j][k]+abs(x));
for(int p=0;p<=l;p++)
{
int d=(a[i+2]+p+20)%10;
dp[i][c][d]=min(dp[i][c][d],dp[i-1][j][k]+abs(x));
}
}
//或者下调x步
if(b[i]<j) x=j-b[i];
else x=10+j-b[i];
dp[i][k][a[i+2]]=min(dp[i][k][a[i+2]],dp[i-1][j][k]+abs(x));
for(int l=0;l<=x;l++)
{
int c=(k-l+20)%10;
dp[i][c][a[i+2]]=min(dp[i][c][a[i+2]],dp[i-1][j][k]+abs(x));
for(int p=0;p<=l;p++)
{
int d=(a[i+2]-p+20)%10;
dp[i][c][d]=min(dp[i][c][d],dp[i-1][j][k]+abs(x));
}
}
}
}
}
}
int ans=0x3f3f3f3f;
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
ans=min(ans,dp
[i][j]);
}
}
cout<<ans<<endl;
}
return 0;
}
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
题意:给两个字符串A,B,每一步可以将连续的1-3个数字上调或下调一位,问将A变成B最少需要几步。
思路:调动一位只能对它的后两位有影响,从第一位开始调,第一位只能通过它自己的变化才能变成目标数字。设dp[i][j][k]表示使i位置变为目标数字,且i+1位置变为数字j,且i+2位置变为数字k,所需要的最少步数。需要注意的一个坑数据就是,000 --> 789,只需要3步,也就是说,变第i位需要固定的x步,i+1可以只变y(y<=x)步,i+2可以只变z(z<=y)步。然后变i位的时候有上调和下调两种方式。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
using namespace std;
char s1[1005],s2[1005];
int a[1010],b[1010];
int n;
int dp[1005][10][10];
int main()
{
while(scanf("%s%s",s1,s2)!=EOF)
{
n=(int)strlen(s1);
for(int i=1;i<=n;i++)
{
a[i]=s1[i-1]-'0';
b[i]=s2[i-1]-'0';
}
memset(dp,0x3f3f3f3f,sizeof(dp));
a[n+1]=b[n+1]=0;
a[n+2]=b[n+2]=0;
dp[0][a[1]][a[2]]=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<10;j++)
{
for(int k=0;k<10;k++)
{
if(dp[i-1][j][k]!=0x3f3f3f3f)
{
int x;
if(b[i]>=j) x=b[i]-j; //将第i位上调x步
else x=10+b[i]-j;
dp[i][k][a[i+2]]=min(dp[i][k][a[i+2]],dp[i-1][j][k]+abs(x));
for(int l=0;l<=x;l++)
{
int c=(k+l+20)%10;
dp[i][c][a[i+2]]=min(dp[i][c][a[i+2]],dp[i-1][j][k]+abs(x));
for(int p=0;p<=l;p++)
{
int d=(a[i+2]+p+20)%10;
dp[i][c][d]=min(dp[i][c][d],dp[i-1][j][k]+abs(x));
}
}
//或者下调x步
if(b[i]<j) x=j-b[i];
else x=10+j-b[i];
dp[i][k][a[i+2]]=min(dp[i][k][a[i+2]],dp[i-1][j][k]+abs(x));
for(int l=0;l<=x;l++)
{
int c=(k-l+20)%10;
dp[i][c][a[i+2]]=min(dp[i][c][a[i+2]],dp[i-1][j][k]+abs(x));
for(int p=0;p<=l;p++)
{
int d=(a[i+2]-p+20)%10;
dp[i][c][d]=min(dp[i][c][d],dp[i-1][j][k]+abs(x));
}
}
}
}
}
}
int ans=0x3f3f3f3f;
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
ans=min(ans,dp
[i][j]);
}
}
cout<<ans<<endl;
}
return 0;
}
相关文章推荐
- 动态规划(5):状态压缩
- 二叉树的镜像
- 利用反汇编手段解析C语言函数
- maven首次体验
- Hello Mr.J——shiro 简单地认识
- linux学习-常规命令使用5
- C++中的 using
- jQuery实现简单图片的轮播(自右向左播放)
- NodeMCU之旅(四):实现Web配置页面
- 聊聊高并发系统之限流特技-1
- 【JavaWeb框架学习】之Hibernate缓存机制、一级缓存和二级缓存介绍
- Sublime Text3设置SublimeREPL快捷键的方法(Python)
- mysql中set autocommit=0与start transaction区别
- Cookie工具类
- 华为OJ 合唱队
- POJ 3126 Prime Path (BFS)
- Silhouettes:聚类结果衡量指标
- Python基础——列表和元组
- 【字符串6】翻转单词顺序列
- 顺序建链表