2020.02.09日常总结——dp例题略讲

25 篇文章 0 订阅
本文介绍了如何解决一个关于骰子游戏的问题,其中每个面的数字与其对面的数字之和为7。目标是在达到特定分数时,找到需要的最小步骤数。文章通过动态规划(dp)的方法来解决这个问题,定义了状态表示达到特定分数且顶面数字的情况,并给出了详细的转移方程和代码实现。
摘要由CSDN通过智能技术生成

D i c e   G a m e \color{green}{Dice\ Game} Dice Game

【 原 题 链 接 】 : \color{blue}{【原题链接】:} 点此进入原题面

【 题 目 大 意 】 : \color{blue}{【题目大意】:} 有一个色子,每个面上有一个数字, x x x对面是 7 − x 7-x 7x,我们可以把色子旋转 90 90 90度,然后把顶面数字加入得分,求最少几步刚刚达到 n n n分。若无解,输出-1

【 思 路 】 : \color{blue}{【思路】:} 很明显的一道 d p dp dp题,但是也稍需思考。

我们很容易想到用 f u f_u fu表示分数刚刚达到 u u u时的步数,答案很好表示,就是 f n f_n fn。但是,我们发现,这样做不好转移。因为转移与顶面的数字相关。

本着 影 响 答 案 的 内 容 就 是 d p 数 组 的 一 维 \color{red}{影响答案的内容就是dp数组的一维} dp这样的思想,所以我们修改我们的定义,即 f u , v f_{u,v} fu,v表示刚刚达到 u u u分且顶面为 v v v时的答案。答案其实也很好表示,即:

min ⁡ 1 ≤ i ≤ 6 { f n , i } \min\limits_{1 \leq i \leq 6} \{f_{n,i} \} 1i6min{fn,i}

转移的时候,因为有了 v v v这一维,转移变得和方便,即:

f n , v = min ⁡ 1 ≤ i ≤ 6 且 i ≠ v 且 i + v ≠ 7 { f n − i , i + 1 } f_{n,v}=\min_{1 \leq i \leq 6且i \neq v且i+v \neq 7} \{ f_{n-i,i}+1 \} fn,v=1i6i=vi+v=7min{fni,i+1}

【 代 码 】 : \color{blue}{【代码】:}

const int inf=0x3f3f3f;
int f[10100][8],n,test_number;
inline void updata(int x,int v){
	for(int i=1;i<=6;i++)
		if (v!=i&&v+i!=7)
			f[x+i][i]=min(f[x+i][i],f[x][v]+1);
}//转移
inline void dp_init(int n){
	for(int i=0;i<=n;i++)
		for(int j=1;j<=6;j++)
			f[i][j]=inf;
	f[0][1]=0;//初始化,注意初始1朝上 
	for(int i=0;i<=n;i++)
		for(int j=1;j<=6;j++)
			updata(i,j);
}//提前计算出答案
inline int answer(int n){
	register int result=inf;
	for(int i=1;i<=6;i++)
		result=min(result,f[n][i]);
	return result==inf?-1:result;
}//计算答案
int main(){
	dp_init(10010);
	scanf("%d",&test_number);
	while (test_number--){
		scanf("%d",&n);
		printf("%d\n",answer(n));
	}
	return 0;
}


**************************
状态:Accepted
得分:100分
备注:没写头文件
**************************
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值