Codeforces 题目传送门 & 洛谷题目传送门

当被数据结构搞自闭的 tzc 信心满满地点开一道 *2400 的 dp 题时……

却发现自己不会做?!

这足以证明蒟蒻 dp 之菜/dk/dk/wq/wq

设 \(a_i=[\text{第一个人会做第}\ i\ \text{题}]\),\(b_i=[\text{第二个人会做第}\ i\ \text{题}]\)

考虑 \(dp\),\(dp_{i,j,x,y}\) 表示现在已经考虑到了第 \(i\) 个人,现在已经消耗了 \(j\) 次偷看的机会,此次向左边的人的偷看机会已经向左边的人偷看 \(x\) 题,此次向左边的人的偷看机会已经向左边的人偷看 \(y\) 题,所能做出的最多题数。如果 \(x=k\) 表示在不消耗新的偷看机会的情况下不能再偷看第一个人的试卷,\(y=k\) 也同理。

分两种情况转移:

  1. 不消耗新的偷看机会,即从 \(dp[i][j][x][y]\) 转移到 \(dp[i+1][j][\min(x+1,k)][\min(y+1,k)]\),此时能多做出一道题当且仅当 \((a_{i+1}\land x+1\leq k)\lor (b_{i+1}\land y+1\leq k)\),即 \(dp[i+1][j][\min(x+1,k)][\min(y+1,k)]\leftarrow dp[i][j][x][y]+(a_{i+1}\land x+1\leq k)\lor (b_{i+1}\land y+1\leq k)\)

  2. 消耗新的偷看机会。还是分两种情况,一是偷看第一个人的试卷,即 \(dp[i+1][j+1][1][\min(y+1,k)]\leftarrow dp[i][j][x][y]+a[i+1]\),第二种是偷看右边人的试卷,即 \(dp[i+1][j+1][\min(x+1,k)][1]\leftarrow dp[i][j][x][y]+b[i+1]\)。

最终答案即为 \(\max dp[n][j][x][y]\)。

这样 DP 时间复杂度为 \(npk^2\),会炸。考虑优化,感性理解一下可知当 \(p\) 比较大的时可以选择将两个人的每道题的答案看完,这样答案即为 \(a_i\lor b_i=1\) 的 \(i\) 的个数。随便算一下就知道这样的 \(p\) 的临界值为 \(2\lceil\dfrac{n}{k}\rceil\),也就是说你只需对 \(p\leq 2\lceil\dfrac{n}{k}\rceil\) 的情况跑一遍上述 DP 即可。时间复杂度也随之降到了 \(n^2k\)。

注意滚动数组优化,否则会 MLE。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=1e3;
const int MAXK=50;
int n,n1,n2,p,k,dp[2][MAXN+5][MAXK+3][MAXK+3];
int isa[MAXN+5],isb[MAXN+5];
int main(){
scanf("%d%d%d",&n,&p,&k);
scanf("%d",&n1);for(int i=1,x;i<=n1;i++) scanf("%d",&x),isa[x]=1;
scanf("%d",&n2);for(int i=1,x;i<=n2;i++) scanf("%d",&x),isb[x]=1;
if(p>=(n+k-1)/k*2){
int ret=0;
for(int i=1;i<=n;i++) ret+=isa[i]|isb[i];
printf("%d\n",ret);return 0;
}
int pre=0,cur=1;memset(dp[pre],192,sizeof(dp[pre]));
dp[pre][0][k][k]=0;
for(int i=1;i<=n;i++){
memset(dp[cur],192,sizeof(dp[cur]));
for(int j=0;j<=p;j++){
for(int x=1;x<=k;x++) for(int y=1;y<=k;y++){
chkmax(dp[cur][j][min(x+1,k)][min(y+1,k)],dp[pre][j][x][y]+((isa[i]&&x<k)||(isb[i]&&y<k)));
if(j<p){
if(isa[i]) chkmax(dp[cur][j+1][1][min(y+1,k)],dp[pre][j][x][y]+1);
if(isb[i]) chkmax(dp[cur][j+1][min(x+1,k)][1],dp[pre][j][x][y]+1);
}
}
} pre^=cur^=pre^=cur;
} int ans=0;
for(int j=0;j<=p;j++) for(int x=1;x<=k;x++) for(int y=1;y<=k;y++)
chkmax(ans,dp[pre][j][x][y]);
printf("%d\n",ans);
return 0;
}

Codeforces 796E - Exam Cheating(dp)的更多相关文章

  1. Codeforces Gym101341K:Competitions(DP)

    http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择 ...

  2. codeforces 711C Coloring Trees(DP)

    题目链接:http://codeforces.com/problemset/problem/711/C O(n^4)的复杂度,以为会超时的 思路:dp[i][j][k]表示第i棵数用颜色k涂完后bea ...

  3. codeforces#1154F. Shovels Shop (dp)

    题目链接: http://codeforces.com/contest/1154/problem/F 题意: 有$n$个物品,$m$条优惠 每个优惠的格式是,买$x_i$个物品,最便宜的$y_i$个物 ...

  4. Codeforces 1051 D.Bicolorings(DP)

    Codeforces 1051 D.Bicolorings 题意:一个2×n的方格纸,用黑白给格子涂色,要求分出k个连通块,求方案数. 思路:用0,1表示黑白,则第i列可以涂00,01,10,11,( ...

  5. Codeforces 1207C Gas Pipeline (dp)

    题目链接:http://codeforces.com/problemset/problem/1207/C 题目大意是给一条道路修管道,相隔一个单位的管道有两个柱子支撑,管道柱子高度可以是1可以是2,道 ...

  6. Codeforces 704C - Black Widow(dp)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 感觉这种题被评到 *2900 是因为细节太繁琐了,而不是题目本身的难度,所以我切掉这种题根本不能说明什么-- 首先题目中有一个非 ...

  7. Codeforces 682B New Skateboard(DP)

    题目大概说给一个数字组成的字符串问有几个子串其代表的数字(可以有前导0)能被4整除. dp[i][m]表示字符串0...i中mod 4为m的后缀的个数 通过在i-1添加str[i]字符转移,或者以st ...

  8. Codeforces 543D Road Improvement(DP)

    题目链接 Solution 比较明显的树形DP模型. 首先可以先用一次DFS求出以1为根时,sum[i](以i为子树的根时,满足要求的子树的个数). 考虑将根从i变换到它的儿子j时,sum[i]产生的 ...

  9. Codeforces 543C Remembering Strings(DP)

    题意比较麻烦 见题目链接 Solution: 非常值得注意的一点是题目给出的范围只有20,而众所周知字母表里有26个字母.于是显然对一个字母进行变换后是不影响到其它字符串的. 20的范围恰好又是常见状 ...

随机推荐

  1. javascript-vue介绍

    vue.js是一个用于创建web交互页面的库 从技术角度讲,vue专注于MVVM模型的viewModel层,它通过双向数据绑定把view层和model层连接起来,实际DOM封装和输出格式都被抽象为Di ...

  2. Noip模拟57 2021.9.20

    规律总结:联考必爆炸 T1 2A 没$A$掉的大水题,但是是真的不知道$000$前面的$00$也算先导$0$,以后要长记性,这种东西不能再错了 再打三遍: $000$前面的$00$也算先导$0$ $0 ...

  3. 【学习笔记】Vizing 定理

    图染色问题的经典结论 定义 称一个边染色方案合法当且仅当每个顶点连出的所有边的颜色都互不相同,如果此时出现了 \(k\) 个颜色那么称该方案是图的一组 \(k\) 染色 一张无向图的边着色数为最小的 ...

  4. 翻转子串 牛客网 程序员面试金典 C++ Python

    反转子串 牛客网 程序员面试金典 C++ Python 题目描述 假定我们都知道非常高效的算法来检查一个单词是否为其他字符串的子串.请将这个算法编写成一个函数,给定两个字符串s1和s2,请编写代码检查 ...

  5. Appium 介绍与环境搭建

    目录 Appium 介绍 APP 自动化测试介绍 什么是 Appium ? Appium 优势 Appium 架构 Appium 生态 Appium 组件 UiAutomator API Bootst ...

  6. Mysql 5.7 集群部署,keepalived

    参考文章: https://blog.csdn.net/f18770366447/article/details/80703347 https://www.cnblogs.com/benjamin77 ...

  7. AndroidStudio中debug.keystore文件不存在解决办法

    Android项目丢失了debug.keystore,直接重新生存一个key. 在cmd下,进入C:\Users\Administrator\.android目录执行命令如下:  keytool -g ...

  8. SpringCloud概念

    SpringCloud概述 1.SpringCloud是什么? 官方解释:  官网: https://spring.io/projects/spring-cloud/  SpringCloud是一系列 ...

  9. 攻防世界 WEB 高手进阶区 XCTF Web_php_unserialize Writeup

    攻防世界 WEB 高手进阶区 XCTF Web_php_unserialize Writeup 题目介绍 题名考点 PHP反序列化漏洞 正则匹配 Writeup <?php class Demo ...

  10. C++ 内存四区 理解总结

    内存模型图(4G) 整体简单说明 32位CPU可寻址4G线性空间,每个进程都有各自独立的4G逻辑地址,其中 03G是用户空间**,**34G是内核空间即3G用户空间和1G内核空间,不同进程相同的逻辑地 ...