Atcoder Educational DP Contest 题解
A - Frog 1/B - Frog 2
入门...
#include<cstdio>
#define abs(a) ((a)>=0?(a):(-(a)))
#define min(a,b) ((a)<(b)?(a):(b))
#define maxn 100050
using namespace std;
int dp[maxn],a[maxn];
int main(){
int n,k=;
scanf("%d",&n);
for (int i=;i<=n;i++)
scanf("%d",&a[i]),dp[i]=1e9;
dp[]=;
for (int i=;i<=n;i++){
for (int j=;j<=k;j++)
if (i-j>) dp[i]=min(dp[i],dp[i-j]+abs(a[i-j]-a[i]));
}
printf("%d\n",dp[n]);
return ;
}
A and B
C - Vacation
$dp[i][0/1/2]$ 表示到第 $i$ 个 这一个选 $0/1/2$ 转移就很显然了....
#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
#define maxn 100050
using namespace std;
int dp[maxn][];
int main(){
int n;
scanf("%d",&n);
for (int i=;i<=n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
dp[i][]=max(dp[i-][],dp[i-][])+a;
dp[i][]=max(dp[i-][],dp[i-][])+b;
dp[i][]=max(dp[i-][],dp[i-][])+c;
}
printf("%d\n",max(max(dp[n][],dp[n][]),dp[n][]));
return ;
}
C
D - Knapsack 1
裸背包
#include<cstdio>
#define ll long long
#define max(a,b) (a>b?a:b)
#define maxn 100050
using namespace std;
ll dp[maxn];
int main(){
int n,W;
scanf("%d%d",&n,&W);
for (int i=;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
for (int j=W;j>=a;j--)
dp[j]=max(dp[j-a]+b,dp[j]);
}
ll ans=;
for (int j=;j<=W;j++)
if (dp[j]>ans) ans=dp[j];
printf("%lld\n",ans);
return ;
}
D
E - Knapsack 2
发现价值比较小,那么换一下 $dp$ 的状态表示
$dp[j]$ 表示价值为 $j$ 的最小重量
答案就从大到小枚举 $\leq W$ 的即可。
#include<cstdio>
#define ll long long
#define max(a,b) (a>b?a:b)
#define maxn 100050
#define min(a,b) (a<b?a:b)
using namespace std;
ll dp[maxn];
int main(){
int n,W;
scanf("%d%d",&n,&W);
for (int j=;j<=1e5;j++)
dp[j]=1e12;
for (int i=;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
for (int j=1e5;j>=b;j--)
dp[j]=min(dp[j-b]+a,dp[j]);
}
for (int i=1e5;i>=;i--)
if (dp[i]<=W) return printf("%d\n",i),;
return ;
}
/*
dp[i][j]表示前i个价值和为j的最小重量
*/
E
F - LCS
裸的最长公共子序列...方案存一下转移路径倒推就好了
#include<cstdio>
#include<cstring>
#define maxn 3005
using namespace std;
int dp[maxn][maxn],last[maxn][maxn];
char s[maxn],t[maxn],w[maxn];
int main(){
scanf("%s%s",s+,t+);
int n=strlen(s+),m=strlen(t+);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++){
if (s[i]==t[j]) {
if (dp[i][j]<dp[i-][j-]+) dp[i][j]=dp[i-][j-]+,last[i][j]=;
}
if (dp[i-][j]>dp[i][j]) dp[i][j]=dp[i-][j],last[i][j]=;
if (dp[i][j-]>dp[i][j]) dp[i][j]=dp[i][j-],last[i][j]=;
}
int x=n,y=m;
while (dp[x][y]){
if (last[x][y]==) w[dp[x][y]]=s[x],x--,y--;else
if (last[x][y]==) x--;else y--;
}
for (int i=;i<=dp[n][m];i++)
printf("%c",w[i]);
printf("\n");
return ;
}
F
G - Longest Path
最长路径,拓扑上dp
#include<cstdio>
#define maxn 100050
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
struct enode{
int nxt,y;
}e[maxn];
int ans=,tot=;
int n,m;
int q[maxn],dp[maxn],first[maxn],goin[maxn];
void adde(int x,int y){
e[tot].nxt=first[x];
e[tot].y=y;
first[x]=tot++;
goin[y]++;
}
void tupu(){
int head=,tail=;
for (int i=;i<=n;i++)
if (!goin[i]) q[++tail]=i;
while (head<=tail){
int x=q[head++];
if (dp[x]>ans) ans=dp[x];
for (int i=first[x];i>=;i=e[i].nxt){
int y=e[i].y;
goin[y]--;
dp[y]=max(dp[x]+,dp[y]);
if (!goin[y]) q[++tail]=y;
}
}
}
int main(){ scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
first[i]=-;
for (int i=;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
adde(x,y);
}
tupu();
printf("%d\n",ans);
return ;
}
G
H - Grid 1
唔...入门dp吧QAQ
#include<cstdio>
#define HR 1000000007
using namespace std;
char s[];
int dp[][];
int main(){
int n,m;
scanf("%d%d",&n,&m);
dp[][]=;
for (int i=;i<=n;i++){
scanf("%s",s+);
for (int j=;j<=m;j++)
if ((i!=||j!=)&&(s[j]!='#')) dp[i][j]=(dp[i-][j]+dp[i][j-])%HR;
}
printf("%d\n",dp[n][m]);
return ;
}
H
I - Coins
概率dp
$dp[i][j]$ 表示前 $i$ 个有 $j$ 个向上的概率
那么对于当前这一个 要不然就向上 要不然就向下
$dp[i][j]=dp[i-1][j-1]*p[i]+dp[i-1][j]*(1-p[i])$
#include<cstdio>
using namespace std;
double p[],dp[][];
int main(){
int n;
scanf("%d",&n);
for (int i=;i<=n;i++)
scanf("%lf",&p[i]);
dp[][]=;
for (int i=;i<=n;i++){
dp[i][]=dp[i-][]*(-p[i]);
for (int j=;j<=i;j++)
dp[i][j]=dp[i-][j-]*p[i]+dp[i-][j]*(-p[i]);
} double ans=;
for (int i=;i<=n;i++)
if (i>n-i) ans+=dp[n][i];
printf("%.10lf\n",ans);
return ;
}
I
J - Sushi
期望dp
$dp[i][j][k]$ 表示 $1$ 有 $i$ 个,$2$ 有 $j$ 个,$3$ 有 $k$ 个的期望
$dp[i][j][k]=dp[i-1][j][k]\times \frac{i}{n}+dp[i+1][j-1][k]\times \frac{j}{n}+dp[i][j+1][k-1]\times \frac{k}{n}+dp[i][j][k]\times \frac{n-i-j-k}{n}+1$
$dp[i][j][k]\times \frac{i+j+k}{n}=dp[i-1][j][k]\times \frac{i}{n}+dp[i+1][j-1][k]\times \frac{j}{n}+dp[i][j+1][k-1]\times \frac{k}{n}+1$
$dp[i][j][k]\times(i+j+k)=dp[i-1][j][k]\times i+dp[i+1][j-1][k]\times j+dp[i][j+1][k-1]\times k+n$
$dp[i][j][k]=dp[i-1][j][k]\times \frac{i}{i+j+k}+dp[i+1][j-1][k]\times \frac{j}{i+j+k}+dp[i][j+1][k-1]\times \frac{k}{i+j+k}+\frac{n}{i+j+k}$
#include<cstdio>
using namespace std;
double dp[][][];
int a[];
int main(){
int n;
scanf("%d",&n);
for (int i=;i<=n;i++){
int x;
scanf("%d",&x);
a[x]++;
}
for (int k=;k<=n;k++)
for (int j=;j<=n;j++)
for (int i=;i<=n;i++)
if (i||j||k) {
if (i) dp[i][j][k]+=dp[i-][j][k]*i/(i+j+k);
if (j) dp[i][j][k]+=dp[i+][j-][k]*j/(i+j+k);
if (k) dp[i][j][k]+=dp[i][j+][k-]*k/(i+j+k);
dp[i][j][k]+=(double)n/(i+j+k);
}
printf("%.15lf\n",dp[a[]][a[]][a[]]);
return ;
} /*
dp[i][j][k]表示当前有i个1 j个2 k个3 的期望步数 dp[0][0][0]=0 dp[i][j][k]=dp[i-1][j][k]*i/n+dp[i+1][j-1][k]*j/n+dp[i][j+1][k-1]*k/n+dp[i][j][k]*(n-i-j-k)/n+1
dp[i][j][k]*(i+j+k)/n=dp[i-1][j][k]*i/n+dp[i+1][j-1][k]*j/n+dp[i][j+1][k-1]*k/n+1
dp[i][j][k]*(i+j+k)=dp[i-1][j][k]*i+dp[i+1][j-1][k]*j+dp[i][j+1][k-1]*k+n
dp[i][j][k]=dp[i-1][j][k]*i/(i+j+k)+dp[i+1][j-1][k]*j/(i+j+k)+dp[i][j+1][k-1]*k/(i+j+k)+n/(i+j+k) */
J
Atcoder Educational DP Contest 题解的更多相关文章
- Atcoder Educational DP Contest I - Coins (概率DP)
题意:有\(n\)枚硬币,每枚硬币抛完后向上的概率为\(p[i]\),现在求抛完后向上的硬币个数大于向下的概率. 题解:我们用二维的\(dp[i][j]\)来表示状态,\(i\)表示当前抛的是第\(i ...
- AtCoder Educational DP Contest 总结
前言 感觉都初一升初二了,再做这个题是不是有点太菜了啊-- 里面大概都是些 DP 板子题(确信,题目质量还挺高的,不过不涉及太难的优化(实际上只有最后一题是斜率优化). 不管了,还是写个 blog 来 ...
- Atcoder Educational DP Contest
前面简单一点的题直接过吧. A 暴力DP B 怎么还是暴力DP C 还是暴力DP D 直接背包 E 这个背包不太一样了,这里有一个技巧,就是因为价值很小,所以直接对价值背包,求出来达到某一个权值最小的 ...
- Sth about Educational DP Contest
Contest Website : atcoder.jp/contests/dp \[\begin{array}{c|C|c|c} TaskNum & TaskName & Statu ...
- Educational DP Contest H - Grid 1 (DP)
题意:有一个\(n\)X\(m\)的图,"#"表示障碍物,"."表示道路,只能向右或向下走,问从左上角走到右下角的方案数. 题解:这题可以用bfs来搞,但dp更 ...
- Educational DP Contest G - Longest Path (dp,拓扑排序)
题意:给你一张DAG,求图中的最长路径. 题解:用拓扑排序一个点一个点的拿掉,然后dp记录步数即可. 代码: int n,m; int a,b; vector<int> v[N]; int ...
- Educational DP Contest F - LCS (LCS输出路径)
题意:有两个字符串,求他们的最长公共子序列并输出. 题解:首先跑个LCS记录一下dp数组,然后根据dp数组来反着还原路径,只有当两个位置的字符相同时才输出. 代码: char s[N],t[N]; i ...
- Educational DP Contest E - Knapsack 2 (01背包进阶版)
题意:有\(n\)个物品,第\(i\)个物品价值\(v_{i}\),体积为\(w_{i}\),你有容量为\(W\)的背包,求能放物品的最大价值. 题解:经典01背包,但是物品的最大体积给到了\(10^ ...
- 【DP】Educational DP Contest
这份 dp 题单的最后几题好难 orz. 前面的题比较简单,所以我会选取一些题来讲,其它的直接看代码理解吧 qwq. 传送门: https://atcoder.jp/contests/dp 全部 AC ...
随机推荐
- Awvs–网络漏洞扫描工具
Awvs漏洞扫描自动化 在WEB安全方面,安全侧使用Acunetix_Web_Vulnerability_Scanner_11.xWEB漏洞扫描工具定期手工对m站和www站进行全站漏洞扫描. 为了防止 ...
- 大数据(bigdata)练习题
1.在HDFS文件系统的根目录下创建递归目录“1daoyun/file”,将附件中的BigDataSkills.txt文件,上传到1daoyun/file目录中,使用相关命令查看文件系统中1daoyu ...
- 【转帖】samba的配置文件smb.conf详细说明
samba的配置文件smb.conf详细说明 https://blog.csdn.net/cqboy1991/article/details/9791033 找时间自己写一个blog 说明一下搭建过程 ...
- 飞腾1500A 上面银河麒麟操作系统 进行远程以及添加用户的方法 linux xrdp
1. 安装远程用的软件: sudo apt-get install xrdp vnc4server xbase-clients systemctl enable xrdp systemctl star ...
- 关于typescript中的枚举你需要知道这些
数字枚举 数字枚举,即枚举里所有属性的值都是数字类型,先看这段代码: enum Colors { Red, Blue, Yellow } console.log(Colors.Red) console ...
- MySQL 并发事务问题以及事务的隔离级别
一.并发事务处理带来的问题 相对于串行处理,并发事务(InnoDB)处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从而可以支持更多用户. 但并发事务处理也会带来一些问题,主要有一下几种 ...
- set-cookie中的SameSite属性
原文:set-cookie中的SameSite属性 再见,CSRF:讲解set-cookie中的SameSite属性 2016-04-14 13:18:42 来源:360安全播报 作者:暗羽喵 阅读: ...
- div可以同时设置背景图片和背景颜色吗?
前言 当然可以同时设置 当图片背景色不透明时 情况一:当图片的长.宽 >= div的长.宽时 我们最终看到div背景是图片,之所以说是最终看到,是因为在页面加载时,我们先看到的div背景是颜色, ...
- JavaScript 的查询机制——LHS 与 RHS
JavaScript 引擎在查找一个变量的时候,有两种查找机制:LHS 和 RHS. RHS 的查询是简单地查找到某个变量的值,而 LHS 则是试图找到变量的容器的本身. 一个简单的例子:当我们执行 ...
- Node.js学习(1)-加载模块require('fs/http/.b/art-template')
node.js既不是语言,也不是框架,它是一个平台 加载模块: 核心模块(require('fs/http')), 自定义模块(var bExport=require('./b'),exports.f ...