Educational DP Contest
Posted 洛浔的小窝喵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational DP Contest相关的知识,希望对你有一定的参考价值。
Educational DP Contest
ATcoder_link
夯实基础的好东西
I
记录一下此时第 i 个有多少概率小于等于 j 的就可以了。
#include<bits/stdc++.h>
using namespace std;
const int N=3005;
#define db double
db dp[N][N];
int n;
db p[N];
int main()
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>p[i];
int ma=n/2;
for(int i=0;i<=ma;i++) dp[0][i]=1;
for(int i=1;i<=n;i++)
db f=1-p[i],z=p[i];
dp[i][0]=dp[i-1][0]*z;
for(int j=1;j<=ma;j++) dp[i][j]=dp[i-1][j]*z+dp[i-1][j-1]*f;
printf("%.10lf",dp[n][ma]);
return 0;
J
期望的经典题型。
首先几个盘子是等价的设 \\(1,2,3\\) 分别有 \\(i,j,k\\) 个。
则有 \\(dp_i,j,k=1+dp_i,j,k*\\fracn-i-j-kn+dp_i-1,j,k*\\fracin+dp_i+1,j-1,k*\\fracjn+dp_i,j+1,k-1*\\frackn\\)
简单化一下式子 \\(n*dp_i,j,k=n+dp_i,j,k*(n-i-j-k)+dp_i-1,j,k*i+dp_i+1,j-1,k*j+dp_i,j+1,k-1*k\\)
这傻逼练 latex 呢是吧 \\((i+j+k)*dp_i,j,k=n+dp_i-1,j,k*i+dp_i+1,j-1,k*j+dp_i,j+1,k-1*k\\)
\\(dp_i,j,k=\\fracn+dp_i-1,j,k*i+dp_i+1,j-1,k*j+dp_i,j+1,k-1*ki+j+k\\)
然后注意下转移顺序就可以了喵。感觉有助于理解期望。
可能比较抽象:期望是转移走的概率,就是每个可能性的期望*概率,所以要从简单向复杂的推,从复杂的往简单的推应该能做但是式子未免太抽象了。反过来是好的!
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int N=305;
#define db double
db dp[N][N][N];
int n;
int cnt[5];
int main()
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
int tmp;
cin>>tmp;
cnt[tmp]++;
for(int k=0;k<=n;k++)
for(int j=0;j<=n;j++)
for(int i=0;i<=n;i++)
if(i||j||k)
if(i)dp[i][j][k]+=dp[i-1][j][k]*i;
if(j)dp[i][j][k]+=dp[i+1][j-1][k]*j;
if(k)dp[i][j][k]+=dp[i][j+1][k-1]*k;
(dp[i][j][k]+=n)/=(i+j+k);
cout<<dp[cnt[1]][cnt[2]][cnt[3]];
return 0;
K
经典博弈题,如果一个点能到达必胜状态它就是必胜的。
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
int f[100005];
int a[105];
int n,k;
int main()
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=k;i++)
for(int j=1;j<=n;j++)
f[i]|=((i-a[j]>=0)&&(!f[i-a[j]]));
puts(f[k]?"First":"Second");
return 0;
Educational Codeforces Round 63-D(基础DP)
题目链接:https://codeforces.com/contest/1155/problem/D
题意:给定n个数,可以选择一段连续子段将其乘x,也可以不操作,求最大连续子段和。
思路:比赛时觉得是dp,但怎么也想不出来QAQ,dp太难了。。。赛后看了别人题解,找到状态和转移方程就很简单了,然而比赛时我就是想不到。。。
考虑下标i:有3种情况,可能[0,i]都没有乘x,可能i乘了x,可能[i,n]都不会乘x。分别用dp[i][0]表示以i结尾的最长子段和且 [0,i]都没乘x,dp[i][1]表示以i结尾的最长子段和且i要乘x,dp[i][2]表示以i结尾的最长子段和且[i,n]都不会乘x。
则状态转移方程为:dp[i][0]=max(dp[i-1],0)+a[i];
dp[i][1]=max(dp[i-1][0],dp[i-1][1],0)+a[i]*x;
dp[i][2]=max(dp[i-1][1],dp[i-1][2],0)+a[i];
加油!!下一次会更好!
AC代码:
#include<cstdio> #include<algorithm> using namespace std; typedef long long LL; int n,x; LL dp[300005][3],ans; int main(){ scanf("%d%d",&n,&x); for(int i=1;i<=n;++i){ LL tmp; scanf("%lld",&tmp); dp[i][0]=max(dp[i-1][0],0LL)+tmp; dp[i][1]=max(dp[i-1][0],max(dp[i-1][1],0LL))+1LL*tmp*x; dp[i][2]=max(dp[i-1][1],max(dp[i-1][2],0LL))+tmp; ans=max(ans,max(dp[i][0],max(dp[i][1],dp[i][2]))); } printf("%lld\n",ans); return 0; }
以上是关于Educational DP Contest的主要内容,如果未能解决你的问题,请参考以下文章