题意:一个跳舞机,分上下左右中,中编号是0,然后从上开始逆时钟编号1、2、3、4,有一串你要踩的序列,从0到周围4个,花费为2,周围两个相邻的动一下是3,跳到对面去是4,同一格踩一下是1,两个脚不能同时踩在同一格,问你这串序列踩完最少的花费。
思路:LRJ黑书上的一道题,三维表示状态,dp[2][i][j],i.j分别表示左右脚放的位置,看见别人滚动数组节省空间,就学着写了,记得黑书上好像也是这样子的
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; int cost[5][5],d[2][5][5]; void init(){ for (int i = 1; i <= 4; i++){ cost[0][i] = cost[i][0] = 2; cost[i][i] = 1; } cost[0][0] = 1; for (int i = 1; i <= 3; i++) cost[i][i+1] = cost[i+1][i] = 3; cost[1][4] = cost[4][1] = 3; cost[1][3] = cost[3][1] = 4; cost[2][4] = cost[4][2] = 4; } int main(){ init(); int a; while (scanf("%d",&a) != EOF && a){ memset(d[0],INF,sizeof(d[0])); d[0][a][0] = d[0][0][a] = 2; int pre = 0,cur; while (scanf("%d",&a) != EOF && a){ cur = pre^1; memset(d[cur],INF,sizeof(d[cur])); for (int j = 0; j <= 4; j++) for (int k = 0; k <= 4; k++) d[cur][a][j] = min(d[cur][a][j],d[pre][k][j]+cost[a][k]); for (int j = 0; j <= 4; j++) for (int k = 0; k <= 4; k++) d[cur][j][a] = min(d[cur][j][a],d[pre][j][k]+cost[a][k]); pre = cur; } int ans = INF; for (int i = 0; i <= 4; i++) for (int j = 0; j <= 4; j++){ if (i == j) continue; ans = min(ans,d[cur][i][j]); } printf("%d\n",ans); } return 0; }