UVa10618
来源:互联网 发布:docker github 源码 编辑:程序博客网 时间:2024/06/05 07:46
题目链接
简介:
跳舞机
分析:
限制条件较多的一个动态规划
状态很好理解,但是限制特别多
d[i][a][b][s]表示到达第i个指示灯的时候,左脚在a,右脚在b,上一次移动的脚为s(没有移动0,左脚1,右脚2)所需的最小花费
将四个方向分别编号为上0,下3,左1,右2.
这样编码的方式有一个方便之处:求相对的方向只要和为3即可
状态转移如下:
- 如果当前是 ’ . ‘,有三种决策
- 选择不动
- 左脚移到其他方向
- 右脚移动到其他方向.
- 如果当前是某一个方向,有两种决策
- 左脚移动到该位置上
- 右脚移动到该位置上.
注意不要枚举不合法的移动:
不合法的移动:
- 左脚在右箭头上,右脚在左箭头上
- 两脚在同一箭头上
- 左脚在右箭头上,但是右脚要移动
- 右脚在左箭头上,但是左脚要移动
代码中,我们采用逆推的方式
//这里写代码片#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int INF=0x33333333;const int L=1;const int R=2;char ss[100];int d[100][4][4][3],action[100][4][4][3];int pos[256],n;char place[]=".LR";int get(int a,int ta){ if (a==ta) return 3; //相同的位置 else if (a+ta==3) return 7; //相对的位置 else return 5; //相邻的位置}int energy(int a,int b,int s,int f,int t,int &ta,int &tb)//a这次的左脚位置 b这次的右脚位置 s上次的动作 f下一次要动的脚 t下一次的动作 ta左脚下次的位置 tb右脚下次的位置 { ta=a; tb=b; if (f==1) ta=t; //下次动作由左脚完成 else if (f==2) tb=t; if (ta==tb) return -1; //踩到同一个位置 if (ta==R&&tb==L) return -1; //背向跳舞机 if (ta==R&&tb!=b) return -1; //a左脚在右脚的位置,但是移动了右脚,无论移动到哪儿,都是不合法的 if (tb==L&&ta!=a) return -1; //b右脚在左脚的位置,但是移动了右脚,无论一定到哪儿,都是不合法的 int e=0; if (f==0) e=0; //没有脚移动 else if (f!=s) e=1; //上一次移动的脚不是现在移动的脚 else { if (f==1) e=get(a,ta); //移动的是左脚 else e=get(b,tb); //移动的是右脚 } return e; }void update(int i,int a,int b,int s,int f,int t)//i踩了几个箭头 a左脚位置 b右脚位置 s上次的动作 f这次要移动的脚 t移动方向 { int ta,tb; int e=energy(a,b,s,f,t,ta,tb); if (e<0) return; int cost=d[i+1][ta][tb][f]+e; //下次移动情况:ta tb int &ans=d[i][a][b][s]; if (ans>cost) { ans=cost; action[i][a][b][s]=f*4+t; // }}void doit(){ n=strlen(ss); memset(d,0,sizeof(d)); 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) continue; for (int s=0;s<3;s++){ //上一次的动作,1左脚,2右脚 d[i][a][b][s]=INF; if (ss[i]=='.') { update(i,a,b,s,0,0); //两脚都不动 for (int t=0;t<4;t++) { update(i,a,b,s,1,t); update(i,a,b,s,2,t); } } else { update(i,a,b,s,1,pos[ss[i]]); update(i,a,b,s,2,pos[ss[i]]); } } } } }}void print(){ int a=1; int b=2; int s=0; for (int i=0;i<n;i++) { int f=action[i][a][b][s]/4; int t=action[i][a][b][s]%4; printf("%c",place[f]); s=f; if (f==1) a=t; else if (f==2) b=t; } printf("\n");}int main(){ pos['U']=0; pos['D']=3; pos['L']=1; pos['R']=2; while (scanf("%s",&ss)!=EOF&&ss[0]!='#') { doit(); print(); } return 0;}
阅读全文
0 0
- UVa10618
- UVA10618 多阶段DP
- UVa10618 Tango Tango Insurrection
- UVA10618 & POJ1726 & ZOJ2120 - Tango Tango Insurrection(比较烦的DP)
- 新建webApi的帮助文档
- Spring 学习笔记2
- Spring 学习笔记3
- Spring 学习笔记4
- Spring 学习笔记6
- UVa10618
- Runtime详解二
- 完美世界校招算法题2017
- Blog15@linux介绍kickstart、dhcp
- Ubuntu数据备份
- 坚持#第231天~零基础自学云计算基础语言应用之python第7节
- 五种傅里叶变换的特性
- ssh
- Navi.Soft31.WinCE框架.开发手册(含下载地址)