跳舞机(Tango Tango Insurrection, UVa 10618)

Problem

题意如紫书,关于cost的计算感觉有些紫书上给的翻译不太好理解:本次无动作cost为0,本次动作和上次动作不一条腿cost为1,本次和上次动作同一条腿,没有涉及移动(只是踩了一下)cost为3,本次和上次动作同一条腿,本次为相邻移动和相对移动时cost分别为5和7。

Solution

  • 条件较多,d(i,a,b,s)表示踩了前i个,当前左右脚在a,b,上次的移动状态为s时以后还会产生的最小代价。倒推,最终答案为d(0,1,2,0)。
  • 代码借鉴了网上高质量的代码,详见注释。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 105,inf = 1e5,Left = 1,Right = 2;//0123 上左右下 
int d[maxn][4][4][3],pos[260],action[maxn][4][4][3];
char mov[10];
string str;
int Cost(int a,int ta)//两次同一只脚动作
{
	if(a==ta) return 3;//本次没有移动 
	if(a+ta==3) return 7;//本次移动到相对位置 
	return 5;//本次移动到相邻位置 
	
} 
int energy(int a,int b,int s,int f,int t,int &ta,int &tb)//f=0,1,2:本次不动,移左脚,移右脚 
{
	if(f==1) ta = t;
	if(f==2) tb = t;
	if(ta==tb) return -1;//移动之后两脚在同一位置 
	if(ta==Right&&tb==Left) return -1; //移动之后背对跳舞机
	if(a==Right&&tb!=b||b==Left&&ta!=a) return -1;//左脚在右但移动了右脚或右脚在左但移动了左脚
	int e = 0;//以下计算本次移动代价 
	if(f==0) e = 0;//本次不移动代价为0 
	else if(f!=s) e = 1;//和上次移动不是同一只脚代价为1 
	else if(f==1) e = Cost(a,ta);//计算与上次移动的脚相同时的代价 
	else e = Cost(b,tb);
	return e;
}
void update(int i,int a,int b,int s,int f,int t)//移动f脚至t
{
	int ta = a,tb = b;
	int e = energy(a,b,s,f,t,ta,tb);
	if(e==-1) return ;
	int cost = d[i+1][ta][tb][f]+e;
	int &ans = d[i][a][b][s];
	if(ans>cost)
	{
		ans = cost;
		action[i][a][b][s] = f*4+t;
	}
} 
void work()
{
	int n = str.length();
	memset(d,0,sizeof(d)); 
	for(int i=n-1;i>=0;i--)
	{
		for(int a=0;a<=3;a++)
		{
			for(int b=0;b<=3;b++)
			{
				if(a==b) continue;
				for(int s=0;s<4;s++)
				{
					d[i][a][b][s] = inf; 
					if(str[i]=='.')
					{
						update(i,a,b,s,0,0);//不动 
						for(int t=0;t<4;t++)
						{
							update(i,a,b,s,1,t);//左脚移动到t 
							update(i,a,b,s,2,t);//右脚移动到t 
						}
					}
					else{//左右脚分别一致目标 
						update(i,a,b,s,1,pos[str[i]]);
						update(i,a,b,s,2,pos[str[i]]);
					} 
				}
			}
		}
	}	
	int a = 1,b = 2,s = 0;
	for(int i=0;i<n;i++)
	{
		int f = action[i][a][b][s]/4,t = action[i][a][b][s]%4;
		cout<<mov[f];
		if(f==1) a = t;
		if(f==2) b = t;
		s = f;
	}
	cout<<endl;
}
int main()
{
//	freopen("1.txt","w",stdout);
	pos['U'] = 0;
	pos['L'] = 1;
	pos['R'] = 2;
	pos['D'] = 3;
	mov[0] = '.';
	mov[1] = 'L';
	mov[2] = 'R';
	while(cin>>str&&str!="#")
	{
		work();
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
{************************************************************** 跳舞机 ver 1.0 作者:萧寒 (chinasf) !QQ:410000 e-Mail:chinasf@hotmail.com 开发环境:Delphi 7.0 , DirectX 9.0 SDK 资源内容:源码+执行文件+资源文件 1.wav 背景声音,也是游戏的核心 L1.Lvl 文本文件,可编辑,是舞步脚本 (由于WAV文件格式太大,所以音乐文件只一个,并且很短,舞步脚本节拍 是随手输入的,调整 metronome 常量可以修改节拍器,我对音乐不了解, 所以我做不了这些事情,sorry.) 一个跳舞机游戏框架,类的独立性不强,因为程序不大;所以很多地方 是简化了与类的交互,但还是具有很强的扩展性。 已公布的源码有:欢乐五子棋(GDI 版和 C#-GDI+ 版本) 该源码的算法简单,只针对游戏编程爱好者和初学者,仅供参考,不得 用于商业用途,另外,图形资源原稿修改于vb所编写的跳舞机,作者是 s5851217@cc.hwh.edu.tw ,该作者vb的代码是GDI写的,用了内存绘图 机制,是个学习的好题材,本程序的舞步脚本格式就是参照他的,只做了 小小改动,thank! 跳舞机的舞步脚本格式如下: 标准 Windows 文本文件格式 行1,保存声音文件的路径和文件名,如: c:1.WAV 从行2开始的格式是 int,int,int,int NextTime(DWORD) 比如: 1001 100 前四位表示四个方向的按键图象,为0 则不现,为1 则显示,1001 表示显示Left 和 Right 100 这个值表示 秒/1000 ,一个时间值,可以用小写 x 表示,默认为2700 ,既 2.7 秒 到行尾则该关结束; 评判是否到下关,可以检查 MainForm 类的 DeadCount 整形 如:失误小于 10 个 ( if MainForm.DeadCount<10 then ContinueNextLevelGame; ) 程序花了两个下班的休息时间,最后祝大家学习愉快!望与爱好者交流探讨与研究。 2003.9.26 00:50 **************************************************************} 下载地址: http://www.bssoft.com.cn/DDR.rar
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈希表扁豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值