SGU 396 Dance it up! 状态压缩dp

题意:一个人要跳由LRUD组成的序列的舞,然后由题目描述中不同的动作变换需要花费不同的值,问最少需要多少花费能跳完整支舞。

题解:dp[ i ][ j ]表示跳到第 i 位置时候状态为 j 的最小花费,其中注意的是每种状态有三种子状态,分别是左脚踩,右脚踩和双脚都不踩,

         那么一共有36种状态(注意RL状态是不合法的),然后path[ i ][ j ]记录路径即可。


Sure原创,转载请注明出处

#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
const int inf = 1 << 29;
const int maxn = 1002;
const int maxt = 40;
int dp[maxn][maxt],path[maxn][maxt];
char str[maxn],ans[maxn][5];
int n,x,y,z;

void init()
{
    memset(path,-1,sizeof(path));
    scanf("%s",str+1);
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<maxt;j++)
        {
            dp[i][j] = inf;
        }
    }
    return;
}

int tran(char c)
{
    if(c == 'L') return 0;
    else if(c == 'U') return 1;
    else if(c == 'R') return 2;
    return 3;
}

char rtran(int c)
{
    if(c == 0) return 'L';
    else if(c == 1) return 'U';
    else if(c == 2) return 'R';
    return 'D';
}

int hash(int L,int R,int S)
{
    int ans = 0;
    if(S == 1) ans = 12;
    if(S == 2) ans = 24;
    ans += L * 3;
    if(L == 0) ans += R-1;
    else if(L == 1) ans += (R+2)%4;
    else if(L == 2)
    {
        if(R == 0) return -1;
        else ans += (R+1)%4;
    }
    else ans += R;
    return ans;
}

bool rhash(int st)
{
    z = st / 12;
    st %= 12;
    if(st == 0) x = 0,y = 1;
    if(st == 1) x = 0,y = 2;
    if(st == 2) x = 0,y = 3;
    if(st == 3) x = 1,y = 2;
    if(st == 4) x = 1,y = 3;
    if(st == 5) x = 1,y = 0;
    if(st == 6) x = 2,y = 3;
    if(st == 7) return false;
    if(st == 8) x = 2,y = 1;
    if(st == 9) x = 3,y = 0;
    if(st == 10) x = 3,y = 1;
    if(st == 11) x = 3,y = 2;
    return true;
}

void relax(int st,int nxt,int pre,int w)
{
    if(dp[st][nxt] > dp[st-1][pre] + w)
    {
        dp[st][nxt] = dp[st-1][pre] + w;
        path[st][nxt] = pre;
    }
    return;
}

void solve()
{
    dp[0][1] = 0;
    for(int i=1;i<=n;i++)
    {
        if(str[i] == 'N')
        {
            for(int j=0;j<12;j++)
            {
                if(rhash(j) == false) continue;
                int xx = x,yy = y;
                for(int k=0;k<36;k++)
                {
                    if(dp[i-1][k] == inf || rhash(k) == false) continue;
                    if(xx == x)
                    {
                        if(yy == y) relax(i,j,k,0);
                        else if(z == 0 || z == 1) relax(i,j,k,3);
                    }
                    else
                    {
                        if(yy == y)
                        {
                            if(z == 0 || z == 2) relax(i,j,k,3);
                        }
                        else relax(i,j,k,10);
                    }
                }
            }
        }
        else
        {
            int pos = tran(str[i]);
            for(int j=0;j<4;j++)
            {
                if(j == pos) continue;
                int nxt = hash(pos,j,1);
                if(nxt != -1)
                {
                    for(int k=0;k<36;k++)
                    {
                        if(dp[i-1][k] == inf || rhash(k) == false) continue;
                        if(pos == x)
                        {
                            if(j == y) relax(i,nxt,k,1);
                        }
                        else if(pos == y) continue;
                        else
                        {
                            if(z == 0 || z == 2)
                            {
                                if(j == y) relax(i,nxt,k,3);
                                else relax(i,nxt,k,10);
                            }
                            else
                            {
                                if(j == y) relax(i,nxt,k,9);
                                else relax(i,nxt,k,10);
                            }
                        }
                    }
                }
                nxt = hash(j,pos,2);
                if(nxt == -1) continue;
                for(int k=0;k<36;k++)
                {
                    if(dp[i-1][k] == inf || rhash(k) == false) continue;
                    if(pos == y)
                    {
                        if(j == x) relax(i,nxt,k,1);
                    }
                    else if(pos == x) continue;
                    else
                    {
                        if(z == 0 || z == 1)
                        {
                            if(j == x) relax(i,nxt,k,3);
                            else relax(i,nxt,k,10);
                        }
                        else
                        {
                            if(j == x) relax(i,nxt,k,9);
                            else relax(i,nxt,k,10);
                        }
                    }
                }
            }
        }
    }
    int res = inf,bj = -1;
    for(int i=0;i<36;i++)
    {
        if(dp[n][i] < res)
        {
            res = dp[n][i];
            bj = i;
        }
    }
    printf("%d\n",res);
    int top = n;
    while(bj != -1)
    {
        rhash(bj);
        ans[top][0] = rtran(x);
        ans[top][1] = rtran(y);
        ans[top][2] = '\0';
        bj = path[top][bj];
        top--;
    }
    for(int i=1;i<=n;i++)
    {
        printf("%s\n",ans[i]);
    }
    return;
}

int main()
{
    while(~scanf("%d",&n))
    {
        init();
        solve();
    }
    return 0;
}

你可能感兴趣的:(c,UP,Path)