您的位置:首页 > 其它

SGU 396 Dance it up! 状态压缩dp

2012-10-23 10:10 351 查看
题意:一个人要跳由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
[i] < res)
{
res = dp
[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: