題目大意
如上圖,這是一個跳舞機,初始狀態兩個腳都在0, 狀態表示為(0, 0), 然後跳舞機會給你一系列舞步方向,例如2,3,4,2,3.......
每次你必須選擇一只腳移動到對應數字方向的各格子上。
例如從初始狀態(0,0),要移到1, 可以選擇左腳或者右腳移上去,對應的狀態為(1, 0), (0,1)
有一個限制,除了初始狀態可以是(0, 0),之後的兩只腳就不能再同時在一個格子上!
移動腳要耗費體力, 從0移動到其它各自都是耗費2, 從1,2,3,4之間,如果是移動到相鄰的格子,比如1->2, 1->4, 3->2, 4->3,耗費體力3
如果是移動到對面的格子,比如1->3, 2->4,耗費體力4。
如果某一步,停止不動,耗費體力1
給一串方向,問最少用多少體力可以完成這些動作?
思路
f(i, j, k), 表示第i步,狀態為(j,k)時花費的最少體力
那麼不難推出轉移方程式:
假設當前這個舞步是在s,那麼符合這一步的所有狀態有:
f(i, 0..4, s), f(i, s, 0...4)
然後可以根據上面的狀態推出下一舞步的最少體力話費
假設下一舞步是next
那麼
如果f(i, j, s), (0<=j<=4)狀態可達
則可推出下一個的狀態
f(i+1, j, s) = f(i, j, k) + 1; // 停在當前不動
f(i+1, next, s) = min{ f(i, j, s) + consume(j, next)}
f(i+1, j, next) = min{ f(i, j, s) + consume(s, next)}
同理,如果f(i, s, j), (0<=j<=4)狀態可達
也可推出下一個狀態:
f(i+1, s, j) = f(i, j, k) + 1; // 停在原地不動
f(i+1, next, j) = min{ f(i, s, j) + consume(s, next)}
f(i+1, s, next) = min{ f(i, s, j) + consume(j, next)}
代碼
/**========================================== * This is a solution for ACM/ICPC problem * * @source:uva-1291 Dance Dance Revolution * @author: shuangde * @blog: blog.csdn.net/shuangde800 * @email: [email protected] *===========================================*/ #include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<cmath> #include<cstring> using namespace std; typedef long long int64; const int INF = 0x3f3f3f3f; const int MAXN = 10010; int n;int dir[MAXN]; int f[MAXN][5][5]; inline int consume(int from, int to){ if(from==to) return 1; if(from==0 || to==0) return 2; int res = abs(from-to); if(res == 1 || res==3) return 3; if(res == 2) return 4; }int main(){ while(~scanf("%d", &dir[0]) && dir[0]){ n = 1; while(~scanf("%d", &dir[n]) && dir[n]) ++n; memset(f, INF, sizeof(f)); for(int i=0; i<=4; ++i) f[0][0][i] = f[0][i][0] = consume(0, i); for(int i=0; i<n-1; ++i){ int s = dir[i]; int next = dir[i+1]; for(int j=0; j<=4; ++j) if(s!=j){ if(f[i][s][j] != INF){ f[i+1][s][j] = min(f[i+1][s][j], f[i][s][j] + 1); for(int k=0; k<=4; ++k){ f[i+1][next][j] = min(f[i+1][next][j], f[i][s][j] +consume(s, next)); f[i+1][s][next] = min(f[i+1][s][next], f[i][s][j] +consume(j, next)); } } if(f[i][j][s] != INF){ f[i+1][j][s] = min(f[i+1][j][s], f[i][j][s] + 1); for(int k=0; k<=4; ++k){ f[i+1][next][s] = min(f[i+1][next][s], f[i][j][s] +consume(j, next)); f[i+1][j][next] = min(f[i+1][j][next], f[i][j][s] +consume(s, next)); } } } } int ans = INF; int s = dir[n-1]; for(int i=0; i<=4; ++i)if(i!=s){ ans = min(ans, min(f[n-1][i][s], f[n-1][s][i])); } printf("%d\n", ans); } return 0;}