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

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

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

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

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

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

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

min 1 i 6 { f n , i } \min\limits_{1 \leq i \leq 6} \{f_{n,i} \}

转移的时候,因为有了 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 \}

\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分
备注:没写头文件
**************************
发布了103 篇原创文章 · 获赞 4 · 访问量 6730

猜你喜欢

转载自blog.csdn.net/ZHUYINGYE_123456/article/details/104239792