Locker UVA - 1631 (dp)
2017-08-17 13:43
417 查看
题目链接:点击打开链接
题目大意:给出一个密码锁的当前状态和最终状态,每一次可以将连续的1~3个向上或者向下转动,问最少要转几次
题目思路:很容易知道是dp题但是还是比较难想出状态转移和定义状态的,如果是第一次写这种类型,首先定义状态dp[i][j][k],代表第i位,第i位为j,i+1位为k,还需转动几次,
为什么要这么定义呢,首先我们知道对于每一位来说肯定是要转到和目标状态相同的,那么我们从最左边的开始考虑,对于当前考虑的这一位,肯定是要变为目标状态的,所以我们去转动他,使其和目标状态一样,当我们转动这一位的时候会给下一位和下两位带来影响,这个时候我们去枚举下一位和下两位所能变动的位数,产生一个新的状态,这里要注意一下第二位转动的次数要小于等于第一位,这样子就产生了状态转移和决策了。
ac代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstring>
#include<iostream>
#include<sstream>
#include<cmath>
#include<vector>
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
const int maxn = 1e7+6;
int a[1050];
int b[1050];
char s1[1050];
char s2[1050];
int n;
int dp[1050][11][11];
int dfs(int now,int a1,int a2)
{
int &ret = dp[now][a1][a2];
if(ret!=-1)
return ret;
if(now>n)
return ret = 0;
ret = INF;
int sumup;
if(a1>b[now]){
sumup = 9-a1+b[now]+1;
}
else{
sumup = b[now]-a1;
}
for(int i = 0;i<=sumup;i++){
for(int j = 0;j<=i;j++){
ret = min(ret,dfs(now+1,(a2+i)%10,(a[now+2]+j)%10)+sumup);
}
}
int sumdn;
if(a1>=b[now]){
sumdn = a1-b[now];
}
else{
sumdn = a1+1+9-b[now];
}
for(int i = 0;i<=sumdn;i++){
for(int j = 0;j<=i;j++){
ret = min(ret,dfs(now+1,(a2-i+10)%10,(a[now+2]-j+10)%10)+sumdn);
}
}
return ret;
}
int main()
{
while(~scanf("%s%s",s1+1,s2+1))
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
n = strlen(s1+1);
memset(dp,-1,sizeof(dp));
for(int i = 1;i<=n;i++){
a[i] = s1[i]-'0';
b[i] = s2[i]-'0';
}
printf("%d\n",dfs(1,a[1],a[2]));
}
}
题目大意:给出一个密码锁的当前状态和最终状态,每一次可以将连续的1~3个向上或者向下转动,问最少要转几次
题目思路:很容易知道是dp题但是还是比较难想出状态转移和定义状态的,如果是第一次写这种类型,首先定义状态dp[i][j][k],代表第i位,第i位为j,i+1位为k,还需转动几次,
为什么要这么定义呢,首先我们知道对于每一位来说肯定是要转到和目标状态相同的,那么我们从最左边的开始考虑,对于当前考虑的这一位,肯定是要变为目标状态的,所以我们去转动他,使其和目标状态一样,当我们转动这一位的时候会给下一位和下两位带来影响,这个时候我们去枚举下一位和下两位所能变动的位数,产生一个新的状态,这里要注意一下第二位转动的次数要小于等于第一位,这样子就产生了状态转移和决策了。
ac代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstring>
#include<iostream>
#include<sstream>
#include<cmath>
#include<vector>
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
const int maxn = 1e7+6;
int a[1050];
int b[1050];
char s1[1050];
char s2[1050];
int n;
int dp[1050][11][11];
int dfs(int now,int a1,int a2)
{
int &ret = dp[now][a1][a2];
if(ret!=-1)
return ret;
if(now>n)
return ret = 0;
ret = INF;
int sumup;
if(a1>b[now]){
sumup = 9-a1+b[now]+1;
}
else{
sumup = b[now]-a1;
}
for(int i = 0;i<=sumup;i++){
for(int j = 0;j<=i;j++){
ret = min(ret,dfs(now+1,(a2+i)%10,(a[now+2]+j)%10)+sumup);
}
}
int sumdn;
if(a1>=b[now]){
sumdn = a1-b[now];
}
else{
sumdn = a1+1+9-b[now];
}
for(int i = 0;i<=sumdn;i++){
for(int j = 0;j<=i;j++){
ret = min(ret,dfs(now+1,(a2-i+10)%10,(a[now+2]-j+10)%10)+sumdn);
}
}
return ret;
}
int main()
{
while(~scanf("%s%s",s1+1,s2+1))
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
n = strlen(s1+1);
memset(dp,-1,sizeof(dp));
for(int i = 1;i<=n;i++){
a[i] = s1[i]-'0';
b[i] = s2[i]-'0';
}
printf("%d\n",dfs(1,a[1],a[2]));
}
}
相关文章推荐
- UVA-1631 Locker(DP)
- UVA 1631-Locker(DP)
- UVa 1631 Locker (DP)
- UVA 1631 Locker——dp
- hdu 4433(uva1631) - Locker - dp
- 【DP 训练】Locker, Tianjin 2012, UVa1631
- HDU 4433 locker(DP)( UVA 1631 - Locker)
- UVA 1631 Locker(HDU 4433)(DP)
- 【Uva 1631】Locker
- Locker UVA - 1631
- UVA - 1631 Locker 记忆化搜索
- UVa 1631 Locker (密码锁)
- uva 1631——Locker
- uva 1631 locker
- UVA 1631 Locker
- UVA1631 - Locker
- 100道动态规划——8 UVA 1631 Locker 递推,状态的定义以及状态转移方程
- UVa 116 Unidirectional TSP(简单旅行商DP)
- UVa 562 Dividing coins(简单DP)
- UVa 11584:Partitioning by Palindromes(DP)