UVA 1631 记忆化搜索

来源:互联网 发布:凌波多媒体教室软件 编辑:程序博客网 时间:2024/06/08 12:21

题意

n位密码锁,每次可以向上或向下转动1-3个密码,问从初始状态转换到目标状态最少需要转动多少次。

题解

设dp[cnt][a][b][c]为当前位为cnt时,cnt位置上的值为a,cnt+1位置上的值为b,cnt+2位置上的值为c。此时将cnt位转动到目标状态,向上或向下转动,根据向上或向下转动后转动的次数,选择转动最少的转动方式,即可得解。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#define INF 1e9using namespace std;int aNum[1010],bNum[1010];int dp[1010][11][11][11];int len;int getUpStep(int now,int dst){    return (dst-now+10)%10;}int getDownStep(int now,int dst){    return (now-dst+10)%10;}int goUp(int now,int up){    return (now+up+10)%10;}int goDown(int now,int down){    return (now-down+10)%10;}int dfs(int cnt,int a,int b,int c){    if(dp[cnt][a][b][c]!=-1)        return dp[cnt][a][b][c];    if(cnt==len)        return 0;    int up=getUpStep(a,bNum[cnt]);    int down=getDownStep(a,bNum[cnt]);    int ans=INF;    for(int i=0;i<=up;i++){        for(int j=0;j<=i;j++){            ans=min(ans,dfs(cnt+1,goUp(b,i),goUp(c,j),aNum[cnt+3])+up);        }    }    for(int i=0;i<=down;i++){        for(int j=0;j<=i;j++){            ans=min(ans,dfs(cnt+1,goDown(b,i),goDown(c,j),aNum[cnt+3])+down);        }    }    return dp[cnt][a][b][c]=ans;}int main(){    char str1[1010],str2[1010];    while(scanf("%s%s",str1,str2)!=EOF){        len=strlen(str1);        for(int i=0;i<len;i++){            aNum[i]=str1[i]-'0';            bNum[i]=str2[i]-'0';        }        memset(dp,-1,sizeof(dp));        aNum[len]=aNum[len+1]=aNum[len+2]=0;        printf("%d\n",dfs(0,aNum[0],aNum[1],aNum[2]));    }    return 0;}
0 0