【动态规划】大富翁 dafuweng

大富翁

dafuweng.pas/c/cpp

1S/256MB

【题目描述】

       想必大家都玩过大富翁的游戏,现在我们把它简单化:现在有N个格子排成一行,最左到右编号为1到N。玩家初始在1号格子,每一轮玩家掷一枚骰子,掷出的点数为1~6,然后玩家向右移动与掷出的点数相同的步数。例如玩家当前站在3号格子上,玩家掷出点数为5,则他会走到8号格子上。现在某些格子上有传送门,我们用(ai, bi)来表示第i个传送门,当玩家恰好停在编号为ai的格子时,会被自动传送到编号为bi的格子。

不过现在玩家有很多个叫做“遥控骰子”的道具,每次使用“遥控骰子”后,玩家都能控制本回合骰子的点数,因为玩家拥有的“遥控骰子”相当多,所以我们可以认为玩家可以始终遥控骰子的点数。

现在的问题是:告诉你这些传送门的位置,你能求出玩家从1号格子到达N号格子最少需要投多少轮骰子吗?

【输入】

输入文件:dafuweng.in

输入的第一行包含两个整数N,M,分别表示格子的数目和传送门的数目。

接下来M行,每行包含两个数ai, bi。分别表示第i号传送门的起点和终点。

【输出】

输入文件:dafuweng.out

输出为一行,包含一个整数,表示玩家从1号格子到达N号格子所需要的最少轮数。

【输入样例】

100 4

7 14

13 30

35 50

40 99

【输出样例】

6

【数据范围】

对于100%的数据,2<=N<=100000,0<=M<=100

对于100%的数据,1<ai<bi<=N,且所有的ai均不相同。

 

 

 

这一题和下棋类似,不过多了一个传送门

 

我们先看看下棋的转移方程f[i]=max{f[i-1],f[i-2],…,f[i-5],f[i-6]}+1;

 

那么这里有了传送门,我们的状态就多了一种f[i]=f[t];

 

 

注意一点,如果有一个传送门是7-->12,那么我们推f[12]的时候从第一个方程会得到f[12]=max{…,f[7],…}+1;  但是事实上我们是不能从7掷骰子过来的(到了7就会自动传送到12!)所以我们还需要判断一下

 

我的存储方法是用hx[x]=y表示从x要传送到y,用h[y]=x表示y是由x传送而来的

值得注意的是题目最后说了一句所有的ai均不相同,但是没有说bi不同!!!

所以h[]数组的下标就会重复,以至于覆盖以前的值,可行的修改方法是写成链表,当然了,由于门最多只有100个,所以我们在数组后面多开一维,写成一个伪链表就ok了!

 

所以存储时小心一些就行了(我就没注意那句话!!!WA了两组)

 

 

 C++ Code

/*
C++ Code
http://blog.csdn.net/jiangzh7
By Jiangzh
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN=100000+10;

int n,m;
int h[MAXN][110],hx[MAXN];
int l[MAXN];
int f[MAXN];

void read()
{
	freopen("dafuweng.in","r",stdin);
	freopen("dafuweng.out","w",stdout);
	
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		h[y][l[y]++]=x;//表示 y 是从 x 传送而来的
		hx[x]=y;//表示从 x 可以传送到 y
	}
}

void work()
{
	memset(f,0x3f,sizeof(f));
	f[1]=0;
	for(int i=1;i<=n;i++)
	{
		if(h[i][0])
			for(int j=0;j<l[i];j++) f[i]=min(f[i],f[h[i][j]]);
		for(int j=1;j<=6;j++)
		{
			if(i-j<1) continue;//越界
			if(hx[i-j]) continue;//位置i-j是会传送的 不能掷骰子
			f[i]=min(f[i],f[i-j]+1);
		}
	}
	printf("%d",f[n]);
}

int main()
{
	read();
	work();
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值