uva 1291(dp)

来源:互联网 发布:重庆优化公司哪家好 编辑:程序博客网 时间:2024/04/29 14:02

题意:有一台跳舞机,中间是0,上左下右分别代表1 2 3 4,初始状态人站在中间,两只脚都踏在0上,然后给出一段序列以0为结束,要按顺序踩出来,从0踏到四个方向需要消耗2点能量,从一个方向到相邻的方向消耗3点能量,从一个方向到对面方向消耗4点能量,在一个方向原地再踩一次消耗1点能量,问把所有序列踩完最少消耗多少能量。
题解:f[i][j][k]表示踩前i步左脚在方向j上右脚在方向k上最少消耗多少能量,那么就要分两种情况讨论:
(1)f[i][j][a[i]] 的前一步是f[i - 1][a[i - 1]][k]或f[i - 1][k][a[i - 1]],这两种情况再加上这一步移动消耗能量取较小值。
(2)f[i][a[i]][j]和上面类似
结果在f[n][a[n]][k]和f[n][k][a[n]]中取最小值就是解。

#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int N = 100000;int n, a[N], f[N][5][5];int Count(int x, int y) {    if (x == 0)        return 2;    int temp = fabs(x - y);    if (temp == 0)        return 1;    if (temp % 2)        return 3;    return 4;}int main() {    while (1) {        n = 1;        scanf("%d", &a[n]);        if (a[n] == 0)            break;        while (a[n]) {            n++;            scanf("%d", &a[n]);        }        n--;        memset(f, INF, sizeof(f));        f[0][0][0] = 0;        for (int i = 1; i <= n; i++) {            for (int j = 0; j <= 4; j++) {                if (j != a[i]) {                    if (a[i - 1] == j) {                        for (int k = 0; k <= 4; k++)                            if (k != a[i - 1] || i == 1) {                                f[i][j][a[i]] = min(f[i][j][a[i]], f[i - 1][j][k] + Count(k, a[i]));                                f[i][a[i]][j] = min(f[i][a[i]][j], f[i - 1][k][j] + Count(k, a[i]));                            }                    }                    else {                        f[i][j][a[i]] = min(f[i][j][a[i]], f[i - 1][j][a[i - 1]] + Count(a[i - 1], a[i]));                        f[i][a[i]][j] = min(f[i][a[i]][j], f[i - 1][a[i - 1]][j] + Count(a[i - 1], a[i]));                    }                }            }        }        int res = INF;        for (int i = 1; i <= 4; i++) {            res = min(res, f[n][i][a[n]]);            res = min(res, f[n][a[n]][i]);        }        printf("%d\n", res);    }    return 0;}
0 0
原创粉丝点击