您的位置:首页 > 其它

ACM-ICPC Live Archive 2031 - Dance Dance Revolution(状态dp)

2016-11-11 17:43 393 查看
思路:

如果跳到第k个舞步时左脚在位置x, 右脚在位置y时所需消耗的最少体力记为d[k,x,y],那么,合法的决策有:

   一:把一只脚从中心位置移到目标位置;

   二:一只脚移动到相邻位置;

   三:一只脚移动到相对位置;

   四:一只脚在原地再踩一下。

   所以 状态转移方程为d[k, a[k],  y] = min(d[ k - 1,  x, y] + effort(x, a[k]));

                                  d[k, x, a[k]] = min( d[k - 1, x, y] + effort(y, a[k]));

  a[k]表示舞曲中第k个箭头的编号;

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
const int maxn = 50008;
using namespace std;

int dp[maxn][5][5];

int effort(int i, int j) {
if (!i) return 2;
if (i < j) swap(i, j);
i -= j;
if (!i) return 1;
if (i == 1 || i == 3) return 3; //1和4是相邻的;
else return 4;
}

int main() {
int t;
while(scanf("%d", &t) && t) {
memset(dp, -1, sizeof(dp));
dp[0][0][0] = 0;
int a, i, j, k;
a = t;
i = 0;
do {
for(j = 0; j < 5; j++)
for(k = 0; k < 5; k++)
if (dp[i][j][k] != -1){
int tmp = dp[i][j][k] + effort(j, a);
dp[i+1][a][k] = (dp[i+1][a][k] > 0? min(dp[i+1][a][k], tmp):tmp);
tmp = dp[i][j][k] + effort(k, a);
dp[i+1][j][a] = (dp[i+1][j][a] > 0? min(dp[i+1][j][a], tmp):tmp);
}
i++;
} while(scanf("%d", &a) && a);
int res = 1<<8;
for(j = 0; j < 5; j++)
for(k = 0; k < 5; k++)
if (dp[i][j][k] != -1)
res = min(res, dp[i][j][k]);
cout<<res<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: