题意:一个人要跳由LRUD组成的序列的舞,然后由题目描述中不同的动作变换需要花费不同的值,问最少需要多少花费能跳完整支舞。
题解:dp[ i ][ j ]表示跳到第 i 位置时候状态为 j 的最小花费,其中注意的是每种状态有三种子状态,分别是左脚踩,右脚踩和双脚都不踩,
那么一共有36种状态(注意RL状态是不合法的),然后path[ i ][ j ]记录路径即可。
Sure原创,转载请注明出处
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; const int inf = 1 << 29; const int maxn = 1002; const int maxt = 40; int dp[maxn][maxt],path[maxn][maxt]; char str[maxn],ans[maxn][5]; int n,x,y,z; void init() { memset(path,-1,sizeof(path)); scanf("%s",str+1); for(int i=0;i<=n;i++) { for(int j=0;j<maxt;j++) { dp[i][j] = inf; } } return; } int tran(char c) { if(c == 'L') return 0; else if(c == 'U') return 1; else if(c == 'R') return 2; return 3; } char rtran(int c) { if(c == 0) return 'L'; else if(c == 1) return 'U'; else if(c == 2) return 'R'; return 'D'; } int hash(int L,int R,int S) { int ans = 0; if(S == 1) ans = 12; if(S == 2) ans = 24; ans += L * 3; if(L == 0) ans += R-1; else if(L == 1) ans += (R+2)%4; else if(L == 2) { if(R == 0) return -1; else ans += (R+1)%4; } else ans += R; return ans; } bool rhash(int st) { z = st / 12; st %= 12; if(st == 0) x = 0,y = 1; if(st == 1) x = 0,y = 2; if(st == 2) x = 0,y = 3; if(st == 3) x = 1,y = 2; if(st == 4) x = 1,y = 3; if(st == 5) x = 1,y = 0; if(st == 6) x = 2,y = 3; if(st == 7) return false; if(st == 8) x = 2,y = 1; if(st == 9) x = 3,y = 0; if(st == 10) x = 3,y = 1; if(st == 11) x = 3,y = 2; return true; } void relax(int st,int nxt,int pre,int w) { if(dp[st][nxt] > dp[st-1][pre] + w) { dp[st][nxt] = dp[st-1][pre] + w; path[st][nxt] = pre; } return; } void solve() { dp[0][1] = 0; for(int i=1;i<=n;i++) { if(str[i] == 'N') { for(int j=0;j<12;j++) { if(rhash(j) == false) continue; int xx = x,yy = y; for(int k=0;k<36;k++) { if(dp[i-1][k] == inf || rhash(k) == false) continue; if(xx == x) { if(yy == y) relax(i,j,k,0); else if(z == 0 || z == 1) relax(i,j,k,3); } else { if(yy == y) { if(z == 0 || z == 2) relax(i,j,k,3); } else relax(i,j,k,10); } } } } else { int pos = tran(str[i]); for(int j=0;j<4;j++) { if(j == pos) continue; int nxt = hash(pos,j,1); if(nxt != -1) { for(int k=0;k<36;k++) { if(dp[i-1][k] == inf || rhash(k) == false) continue; if(pos == x) { if(j == y) relax(i,nxt,k,1); } else if(pos == y) continue; else { if(z == 0 || z == 2) { if(j == y) relax(i,nxt,k,3); else relax(i,nxt,k,10); } else { if(j == y) relax(i,nxt,k,9); else relax(i,nxt,k,10); } } } } nxt = hash(j,pos,2); if(nxt == -1) continue; for(int k=0;k<36;k++) { if(dp[i-1][k] == inf || rhash(k) == false) continue; if(pos == y) { if(j == x) relax(i,nxt,k,1); } else if(pos == x) continue; else { if(z == 0 || z == 1) { if(j == x) relax(i,nxt,k,3); else relax(i,nxt,k,10); } else { if(j == x) relax(i,nxt,k,9); else relax(i,nxt,k,10); } } } } } } int res = inf,bj = -1; for(int i=0;i<36;i++) { if(dp[n][i] < res) { res = dp[n][i]; bj = i; } } printf("%d\n",res); int top = n; while(bj != -1) { rhash(bj); ans[top][0] = rtran(x); ans[top][1] = rtran(y); ans[top][2] = '\0'; bj = path[top][bj]; top--; } for(int i=1;i<=n;i++) { printf("%s\n",ans[i]); } return; } int main() { while(~scanf("%d",&n)) { init(); solve(); } return 0; }