您的位置:首页 > 编程语言 > Go语言

UVa 10618 Tango Tango Insurrection

2016-09-07 14:46 288 查看

 

本质上就是个简单的动规,但是各种条件限制太鬼畜了……

强行肝了大概四个多小时总算肝过去了,其中有三个小时是没发现输出代码有bug,一直在调已经对了的其他部分……

开四维数组f[决策步数][左脚位置][右脚位置][移动情况(不动|动左脚|动右脚)]=最小能量消耗,再开一个四维数组存储路径。

如果是‘.’那么枚举各种走法取最优方案,如果是按键,枚举左脚或者右脚去踩,取最优方案。

由于前一步的动作会影响到下一步的能量消耗,所以需要倒着动规。原本写了倒序循环的动规,在↑那心力交瘁的三个小时里改成了类DFS的形式……

代码写得很详细了:

//紫书P290
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int mxn=90;
struct node{
int l,r,last;
}ap[mxn][6][6][6];
int f[mxn][6][6][6];
//[已决策步数][左脚(上,下,左,右)][右脚(上,下,左,右)][上次移动脚(无,左,右)]
//                 0  1  2   3                      0   1  2
char s[mxn];
int n;
bool pd(int l,int r,int nl,int nr){//移动合法性判断
if(nl==l && nr==r)return 1;
if(nl==l)//左脚不动
if(nr!=l && l!=3)return 1;
if(nr==r)//右脚不动
if(nl!=r && r!=2)return 1;
return 0;
}
int cost(int f,int t,int last,int now){//起点,终点,上次移动脚,本次移动脚
if(last!=now)return 1;//无动作
if(f==t)return 3;//只踩不移动
if(f!=(t^1))return 5;//移动到相邻位置
return 7;//移动到相对位置
}
int dp(int i,int l,int r,int last){
int& ans=f[i][l][r][last];//动规答案
node& a=ap[i][l][r][last];//路径
if(ans!=0x3f3f3f3f)return ans;
if(i==n)return ans=0;//到达起始状态,递归返回
if(s[i]=='.'){
//不移动
ans=min(ans,dp(i+1,l,r,0));
a.l=l;a.r=r;a.last=0;
//四方向移动
for(int j=0;j<4;j++){
//动左脚
if(pd(l,r,j,r)){
int tmp=dp(i+1,j,r,1)+cost(l,j,last,1);
if(ans>tmp){
ans=tmp;
a.l=j;a.r=r;a.last=1;
}
}
//动右脚
if(pd(l,r,l,j)){
int tmp=dp(i+1,l,j,2)+cost(r,j,last,2);
if(ans>tmp){
ans=tmp;
a.l=l;a.r=j;a.last=2;
}
}
}
return ans;
}
//    else{
int dir=0;//目标移动方向
switch(s[i]){
case 'L':{dir=2;break;}
case 'R':{dir=3;break;}
case 'U':{dir=0;break;}
case 'D':{dir=1;break;}
}

//动右脚
if(pd(l,r,l,dir)){
int tmp=dp(i+1,l,dir,2)+cost(r,dir,last,2);
if(tmp<ans){
ans=tmp;
a.l=l;a.r=dir;a.last=2;
}
}
//动左脚
if(pd(l,r,dir,r)){
int tmp=dp(i+1,dir,r,1)+cost(l,dir,last,1);
if(tmp<ans){
ans=tmp;
a.l=dir;a.r=r;a.last=1;
}
}
return ans;
//    }
}
void Print(){//输出方案
int nl=2,nr=3,last=0;//初始状态
for(int i=0;i<=n;i++){
int tpl=nl,tpr=nr,tplast=last;
if(i>0){
if(last==0)printf(".");
else if(last==1)printf("L");
else printf("R");
}
nl=ap[i][tpl][tpr][last].l;
nr=ap[i][tpl][tpr][last].r;
last=ap[i][tpl][tpr][last].last;
}
return;
}
int main(){
int i,j;
while(scanf("%s",s) && s[0]!='#'){
memset(f,0x3f,sizeof f);
n=strlen(s);
dp(0,2,3,0);//从初始状态开始动规
Print();
printf("\n");
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: