洛谷P1373 小a和uim之大逃离

本文介绍了一种使用动态规划解决两个角色在网格中吸取魔液的问题。通过定义状态和转移方程,实现了对任意网格中魔液的最优吸取策略的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.前言

我好弱啊,根本做不出啊~我开始怀疑我学了动规没......

首先瓶子容量要++,然后小a和uim是一起走的,只是轮流吸魔液而已。

2.解法

开一个数组f[i][j][k][p]表示在(i,j)格子处,二人魔液相差k,是第p个人吸。

那么uim吸魔液可以看成是小a扔掉一些魔液。bob表示瓶子容量,得到状态转移方程:

f[i][j][k][0]+=f[i-1][j][(bob+k-ma[i][j])%bob][1]+f[i][j-1][(bob+k-ma[i][j])%bob][1];

f[i][j][k][1]+=f[i-1][j][(k+ma[i][j])%bob][0]+f[i][j-1][(k+ma[i][j])%bob][0];

初始:f[i][j][ma[i][j]][0]=1。就是小a吸这个格子的魔液。

最后求所有f[i][j][0][1]的和即可。

注意常数优化。

3.代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<climits>
#include<iomanip>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
int read(){
	int w=1,q=0;char ch=' ';
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar();
	return w*q;
}
int n,m,bob,mod=1000000007;
int ma[805][805];
int f[805][805][17][2];
int main()
{
	int i,j,k,ans=0,kl;
	n=read();m=read();bob=read();bob++;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			ma[i][j]=read(),ma[i][j]=ma[i][j]%bob,f[i][j][ma[i][j]][0]=1;
	for(i=1;i<=n;i++)
	for(j=1;j<=m;j++)
	for(k=0;k<=bob;k++){
		f[i][j][k][0]+=f[i-1][j][(bob+k-ma[i][j])%bob][1];
		f[i][j][k][0]%=mod;
		f[i][j][k][0]+=f[i][j-1][(bob+k-ma[i][j])%bob][1];
		f[i][j][k][0]%=mod;
		f[i][j][k][1]+=f[i-1][j][(ma[i][j]+k)%bob][0];
		f[i][j][k][1]%=mod;
		f[i][j][k][1]+=f[i][j-1][(ma[i][j]+k)%bob][0];
		f[i][j][k][1]%=mod;
	}
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)ans=(ans+f[i][j][0][1])%mod;
	printf("%d",ans);
   	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值