HDU 4433 DP

题意

给1000个数字,每次可以转动1-3连续位,问从一个状态转到另一个状态最少需要多少步。

题解

比赛时候想复杂了,这道题跟BFS没有任何关系。不过还是有很多神牛用记忆化搜索过了。主要就是设计DP状态,网上有一种比较好想的状态,dp[i][j][k]代表第i个位置已经合法了,j代表第i+1个位置向上转动了j步,k代表第i+2个位置向上转动了k步。这样的话,我们就可以很轻松的进行状态转移。

注意事项

唯一需要特别注意的是在状态转移的过程中需要取模,因为操作之后会出现>=10以及<0的情况,需要进行取模处理。

代码

#include<bits/stdc++.h>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(t) while(t)
#define MEM(a,b) memset(a,b,sizeof(a))
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-10
#define MAXN 1010
#define MOD 1000000007
#define COUT(x) cout<<x<<endl
using namespace std;
char s1[MAXN],s2[MAXN];
int i1[MAXN],i2[MAXN];
int dp[MAXN][15][15];
int main() {
    W(~scanf("%s%s",s1,s2)) {
        int len=strlen(s1);
        MEM(dp,INF);
        dp[0][0][0]=0;
        UP(k,0,len) {
            UP(i,0,10) {
                UP(j,0,10) {
                    int up=(s2[k]-s1[k]-i+20)%10;
//                    COUT(k<<" "<<i<<" "<<j<<" "<<up);
                    int down=10-up;
//                    COUT(up<<" "<<down);
                    UP(p,0,up+1) {
                        UP(q,0,p+1) {
                            dp[k+1][(j+p)%10][q]=min(dp[k+1][(j+p)%10][q],dp[k][i][j]+up);
                        }
                    }
                    UP(p,0,down+1) {
                        UP(q,0,p+1) {
                            dp[k+1][(j-p+10)%10][(10-q)%10]=min(dp[k+1][(j-p+10)%10][(10-q)%10],dp[k][i][j]+down);
                        }
                    }
                }
//            COUT(k);
            }
        }
        printf("%d\n",dp[len][0][0]);
    }
}

猜你喜欢

转载自blog.csdn.net/zhenlingcn/article/details/78213817