📂题解
🔖DP
2023-03-01 16:25阅读: 30评论: 0推荐: 0

ABC.E-DP题目集锦

ABC266E. Throwing the Die

题意:有 n 次扔骰子机会,每次随机扔到 [1,6] 中的一个整数,每次扔完可以选择结束游戏(此时游戏结果为扔到的点数)或者再扔一次,求最佳策略下结果的期望。

fi 表示有 i 次机会时的得分期望,则 fi 可以由 fi1 转移而来:如果第一次扔到的值小于 fi1,那么继续游戏,答案为 fi1;如果大于 fi1,那么结束游戏,答案为当前扔到的值。

{% note success code: %}

#include<bits/stdc++.h>
using namespace std;
long double g[110];
int main() {
	int n;
	cin>>n;
	g[1]=3.5;
	for(int i=2;i<=n;i++)
		for(int j=1;j<=6;j++)
			g[i]+=max((long double)j,g[i-1])/6;
	printf("%.7Lf\n",g[n]);
	return 0;
}

{% endnote %}

ABC265E. Warp

题意:平面直角坐标系,一开始你在 (0,0),每次可以从以下三种方向中选择一种移动:(A,B),(C,D),(E,F);有 m 个障碍物,第 i 个位于 (xi,yi),求不碰到障碍物的情况下走 n 步的方案数。

f[i][j][k] 表示走 i 步 1 操作、j 步 2 操作,k 步 3 操作的方案数,则

f[i][j][k]={0,        if (iA+jC+kE,iB+jD+kF) is an obstaclef[i1][j][k]+f[i][j1][k]+f[i][j][k1],  otherwise

由于在每一层中 i+j+k 为定值,可以优化掉一维状态 k

{% note success code: %}

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int x[3],y[3];
int f[310][310];
pair<int,int> t[100010];
set<pair<int,int> > s;
int main() {
	int n,m;
	cin>>n>>m;
	for(int i=0;i<3;i++)
		cin>>x[i]>>y[i];
	for(int i=1;i<=m;i++) {
		cin>>t[i].first>>t[i].second;
		s.insert(t[i]);
	}
	f[0][0]=1;
	for(int len=1;len<=n;len++) {
		for(int i=len;i>=0;i--)
			for(int j=len-i;j>=0;j--) {
				int k=len-i-j;
				int nowx=i*x[0]+j*x[1]+k*x[2];
				int nowy=i*y[0]+j*y[1]+k*y[2];
				auto tmp=s.lower_bound(make_pair(nowx,nowy));
				if(tmp!=s.end()&&(*tmp)==make_pair(nowx,nowy)) f[i][j]=0;
				else {
					if(i>0) (f[i][j]+=f[i-1][j])%=mod;
					if(j>0) (f[i][j]+=f[i][j-1])%=mod;
				}
			}
	}
	int ans=0;
	for(int i=0;i<=n;i++)
		for(int j=0;j<=n-i;j++)
			(ans+=f[i][j])%=mod;
	cout<<ans<<endl;
	return 0;
}

{% endnote %}

ABC263E. Sugoroku 3

题意:有 n 个格子,第 i 个格子有一个 [0,ai] 的骰子,每到一个格子都会扔一次该格子的骰子,扔到几往前走几步,问走到 n 的期望步数。

f[i] 表示从 in 的期望步数,则

f[i]=j=0ai1ai+1(f[i+j]+1)=1ai+1(f[i]+1)+1ai+1j=1ai(f[i+j]+1)=1ai+1f[i]+1ai+1(1+j=1ai(f[i+j]+1))aiai+1f[i]=1ai+1(1+j=1ai(f[i+j]+1))f[i]=1ai(1+j=1ai(f[i+j]+1))

可以使用前缀和维护。

{% note success code: %}

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int a[200010],inv[200010];
int f[200010],suf[200010];
int main() {
	int n;
	cin>>n;
	inv[1]=1;
	for(int i=2;i<=n;++i)
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=1;i<n;i++)
		cin>>a[i];
	f[n]=suf[n]=0;
	for(int i=n-1;i>0;i--) {
		int x=(suf[i+1]-suf[i+a[i]+1]+1+mod)%mod;
		f[i]=(1ll*x*inv[a[i]]+1)%mod;
		suf[i]=(suf[i+1]+f[i])%mod;
	}
	cout<<f[1]<<endl;
	return 0;
}

{% endnote %}

ABC253E. Distance Sequence

题意:问有多少个序列 a 满足 1in,aim1i<n,|ai+1ai|K

f[i][j] 表示考虑前 i 位,第 i 位为 j 的方案数,则

f[i][j]=k=1jKf[i1][k]+k=j+Kmf[i1][k]

可以使用前缀和维护。

{% note success code %}

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int n,m,k,f[1010][5010];
int s[5010];
int main() {
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++)
		f[1][i]=1,s[i]=(s[i-1]+f[1][i])%mod;
	for(int i=2;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			f[i][j]=((s[max(j-k,0)]+s[m])%mod-s[min(j+k-1,m)]+mod)%mod;
			if(!k) f[i][j]=(f[i][j]-f[i-1][j]+mod)%mod;
		}
		for(int j=1;j<=m;j++)
			s[j]=(s[j-1]+f[i][j])%mod;
	}
	cout<<s[m]<<endl;
	return 0;
}

{% endnote %}

ABC251E. Takahashi and Animals

题意:有 n 个动物,每次操作可以花费 ai 的代价投喂第 ii+1 个动物(特殊地,可以花费 an 的代价投喂第 n 和第 1 个动物)。求喂完每个动物至少一次的最小代价。

f[i][0/1][0/1] 表示考虑前 i 个动物,第 1 个动物选/不选,第 i 个动物选/不选的最小代价,则

{f[i][j][0]=f[i1][j][1]f[i][j][1]=min(f[i1][j][0],f[i1][j][1])+ai

{% note success code %}

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[600010],f[600010][2][2];
signed main() {
	int n,ans=1e18;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	f[1][1][1]=a[1],f[1][0][0]=0;
	f[1][1][0]=f[1][0][1]=1e18;
	for(int i=2;i<=n;i++) {
		for(int j=0;j<=1;j++) {
			f[i][j][1]=min(f[i-1][j][0],f[i-1][j][1])+a[i];
			f[i][j][0]=f[i-1][j][1];
		}
	}
	cout<<min({f[n][1][0],f[n][0][1],f[n][1][1]})<<endl;
	return 0;
}

{% endnote %}

ABC249E. RLE

对于一个小写字母组成的字符串 S,可以如下生成一个字符串 T:将 S 中每个极长的同字符子串替换为“字符+字符个数”的形式。例如 S=aaabcc 生成 T=a3b1c2。求有多少个长度为 n 的字符串 S 满足 lenT<lenS

f[i][j] 表示 S 的长度为 iT 的长度为 j 的方案数,则

f[i][j]=(261)kif[ik][jlog10(k)]

转化一下求和方式:

f[i][j]=(261)klog10i10k1l<10kf[il][jk]

其中第二个 可以使用前缀和维护。复杂度 n2logn

{% note success code %}


{% endnote %}

posted @   曹轩鸣  阅读(30)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起