UVA10618 多阶段DP

来源:互联网 发布:公积金贷款的软件 编辑:程序博客网 时间:2024/05/16 05:10

题意

跳舞机,需要按给出的方向序列踩箭头。一个箭头可以由左脚踩,也可以由右脚踩。正常情况下,不能出现左脚在右,右脚在左的情况。但是,可以出现,左脚在右,右脚在上或在下的情况,此时,在左脚移动前,右脚不能移动。当出现箭头时,即便你的脚在这个箭头上,也需要踩一下。如果这只脚上个时间单位没有任何动作,则消耗1单位能量。如果这只脚上个时间单位没有移动,则消耗3单位能量。如果这只脚上个时间单位移动到相邻箭头,消耗5单位能量。如果这只脚上个单位移动到相对箭头,消耗7单位能量。求如何踩所消耗的能量最少。

题解

多阶段DP。用dp[i][a][b][s]代表已经踩了i个箭头,左脚在a箭头上,右脚在b箭头上,上一个阶段移动的脚为s(0代表没有脚移动,1代表左脚移动,2代表右脚移动)。如果下一步是’.’则有三种决策方案,左脚移动到另一个箭头,右脚移动到另一个箭头,不移动。如果下一步是四个箭头之一,则有两种决策方案,左脚移动到该箭头,右脚移动到该箭头。

注意事项

本题条件判断比较多,特别要注意判断是否相等的等号(==)不要写成=。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int dp[100][4][4][3];const int LEFT=1,RIGHT=2;char foot[]=".LR";char chc[256];struct Node{    int f,t;};Node action[100][4][4][3];int getAdd(int a,int b){    if(a==b)        return 3;    else if(a+b==3)        return 7;    else        return 5;}int update(int i,int a,int b,int s,int t,int f,int &ta,int &tb){    ta=a,tb=b;    if(f==LEFT){        ta=t;    }else if(f==RIGHT){        tb=t;    }    if(ta==tb){        return -1;    }else if(ta==RIGHT&&tb==LEFT){        return -1;    }else if(b==LEFT&&ta!=a){        return -1;    }else if(a==RIGHT&&tb!=b){        return -1;    }    if(f==0){        return 0;    }else if(f!=s){        return 1;    }else{        if(f==LEFT){            return getAdd(a,ta);        }else{            return getAdd(b,tb);        }    }}void energy(int i,int a,int b,int s,int t,int f){    int ta,tb;    int v=update(i,a,b,s,t,f,ta,tb);    if(v<0)        return ;    int& ans=dp[i][a][b][s];    if(ans>v+dp[i+1][ta][tb][f]){        ans=v+dp[i+1][ta][tb][f];        action[i][a][b][s]=(Node){f,t};    }}int main(){    //freopen("d://input.txt","r",stdin);    //freopen("d://output.txt","w",stdout);    char ch[105];    chc['U']=0,chc['L']=1,chc['R']=2,chc['D']=3;    while(scanf("%s",ch)){        if(ch[0]=='#')            break;        int n=strlen(ch);        memset(dp,0,sizeof(dp));        for(int i=n-1;i>=0;i--){            for(int a=0;a<4;a++){                for(int b=0;b<4;b++){                    if(a!=b){                        for(int s=0;s<3;s++){                            dp[i][a][b][s]=n*10;                            if(ch[i]=='.'){                                energy(i,a,b,s,0,0);                                for(int k=0;k<4;k++){                                    energy(i,a,b,s,k,LEFT);                                    energy(i,a,b,s,k,RIGHT);                                }                            }else{                                energy(i,a,b,s,chc[ch[i]],LEFT);                                energy(i,a,b,s,chc[ch[i]],RIGHT);                            }                        }                    }                }            }        }        int a=LEFT,b=RIGHT,s=0;        for(int i=0;i<n;i++){            int f=action[i][a][b][s].f;            printf("%c",foot[f]);            int t=action[i][a][b][s].t;            s=f;            if(f==LEFT){                a=t;            }else if(f==RIGHT){                b=t;            }        }        printf("\n");    }    return 0;}
0 0