UVALive 2031 Dance Dance Revolution

题目大意:一个跳舞机,分上下左右中,中编号是0,然后从上开始逆时钟编号1、2、3、4,有一串你要踩的序列,从0到周围4个,花费为2,周围两个相邻的动一下是3,跳到对面去是4,同一格踩一下是1,两个脚不能同时踩在同一格,问你这串序列踩完最少的花费。

思路:动态规划的思想应该挺明确的,思路也挺清晰地,设d[ i ][ j ][ k ] 表示踩完第i个,左脚在i号位置,右脚在j号位置的最小值,状态转移方程为d[ i ][ pos ][ k ] = min(d[ i-1 ][ a ][ k ] + cost[a,pos]),d[ i ][ j ][ pos ] = min( d[ i -1 ][ j ][ a ] + cost[a,pos]) ,pos为第i个应踩的位置,前者为左脚踩过来,后面是右脚。

由于没告诉范围,掀开始我就开了个10^6的dp数组,可是一直都是TLE,感觉不会超时,然后看了下别人的,他们都是用滚动数组的,我改了一下,一交,马上AC。。 之后我把前面TLE那个改为10^5的数组,AC了,后来一看,果然是 memset 初始化的问题。。。感觉以后那种数组范围不确定的时候还是用滚动数组好一点。。 = =

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int INF = 0x0fffffff ;

int cost[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 d[2][5][5];

int main()
{
    init();
    int a;
    while(~scanf("%d",&a)&&a)
    {
        memset(d[0],0x7f,sizeof(d[0]));
        d[0][a][0] = d[0][0][a] = 2;
        int pre = 0;
        int cur ;
        while(scanf("%d",&a)&&a)
        {
            cur = pre^1;
            memset(d[cur],0x7f,sizeof(d[cur]));
            for(int j = 0;j<=4;j++)
                for(int k = 0;k<=4;k++)
                    d[cur][a][j] = min(d[pre][k][j] + cost[a][k],d[cur][a][j]);
            for(int j = 0;j<=4;j++)
                for(int k = 0;k<=4;k++)
                    d[cur][j][a] = min(d[pre][j][k] + cost[a][k],d[cur][j][a]);
            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(d[cur][i][j],ans);
            }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(UVALive 2031 Dance Dance Revolution)