Codeforces Round #408 (Div. 2) E

来源:互联网 发布:桌面日历软件 编辑:程序博客网 时间:2024/06/12 08:27

E. Exam Cheating

题目链接:E. Exam Cheating
题意是有个女同学要作弊,总共有n道题,旁白有两位学霸,但是他们分别完成了r道题和s道题(按题号严格递增)。这位同学要作弊总共能看p次,每次只能看一位同学的最多连续k道题,只有学霸完成了的题目才能看。问最多能看多少道题。

感觉很巧妙的dp题,一开始我以两位学霸完成了题目为时间轴,但是后来发现有相互覆盖的情形。看了别人的状态后,是这样的:以题目为时间轴,dp[i][a][b][x]代表前i道题看了x眼且第一个学霸还剩下a道题,第二个学霸剩下b道题可以看。
解释一下a b 这个状态吧,我也是看挺久才理解的。
以第一个样例为例
6 2 3
3 1 3 6
4 1 2 5 6
总共有 1 2 3 4 5 6 六道题(加粗代表学霸已经完成的题目)
第一个1 2 3 4 5 6
第二个1 2 3 4 5 6
那么由于每次能最多看连续k个题,毫无疑问我们肯定就看k个题
于是假设在第二题处看了第二个人一眼 状态就是dp[2][0][2][1] ,除去了当前看这道题,对于第二个人我们还能往后面再看2个题
假设在第一道题处看了第一个人一眼,那么就是dp[1][2][0][1]
然后说一下转移,由于每次可以选择看或者不看
假设不看
dp[i][a][b][x] = max(dp[i-1][a+1][b+1][x] , dp[i][a][b][x])
如果看呢
比如看了第一个人,那么第一个人肯定还会剩下k-1道题可以看。
dp[i][k-1][b][x] = max(dp[i][a][b][x] , dp[i-1][a][b+1][x - 1])
看了第二个人也同理
还有就是当a b 等于0的时候要特殊处理,a b等于0的时候仍然可以转移,但是方程就要变动一下了由于比较复杂直接贴代码吧
数据范围比较大避免MLE就用滚动数组来代替

#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<list>#include<stack>#include<queue>#include<iostream>#include<stdlib.h>using namespace std;#define  LONG long longconst int   INF=0x3f3f3f3f;const LONG  MOD=1e9+ 7;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10#define lson  l , mid , rt<< 1#define rson  mid + 1 ,r , (rt<<1)+1#define root 1, m , 1int A[5010] ;int B[5010] ;int dp[2][55][55][500] ;int ab(int x){    if(x < 0 )return 0 ;    return x;}int Cei(int a , int b){    if(a % b != 0) return a/b + 1;    return a / b;}int main(){    int n , p , k ;    clr0( A ) ;    clr0( B ) ;    clr2( dp ) ;    cin >> n >> p >>k ;    if( p > 2 * Cei(n , k) ) p =2 * Cei(n,k) ;    int xx ;    int tt ;    cin >> tt ;    for(int i = 1 ; i <= tt ;++i)        cin >> xx , A[xx] = 1 ;    cin >> tt ;    for(int i = 1 ; i <= tt ; ++ i)        cin >> xx , B[xx] = 1 ;    int pre = 0 , now = 1;    dp[0][0][0][0] = 0 ;    int ans = 0 ;    for(int i = 1  ; i <= n ; ++ i)    {        for(int x = 0 ; x <= p ; ++ x)        {            for(int a = 0 ; a <= k - 1 ; ++ a)            {                for(int b = 0 ; b <= k - 1 ; ++ b)                {                    if(b != 0 && a== 0)                    {                        dp[now][k-1][(b-1)][x +1] = max(dp[now][k-1][(b-1)][x+1], dp[pre][a][b][x] + (A[i] | B[i]) );                        dp[now][a][b-1][x] = max(dp[now][a][b-1][x] , dp[pre][a][b][x] + B[i]) ;                        dp[now][a][k-1][x+1] = max(dp[now][a][k-1][x+1] , dp[pre][a][b][x] +  B[i]) ;                    }                    else if( b == 0 && a == 0)                    {                        dp[now][k-1][b][x+1] = max(dp[now][k-1][b][x+1] , dp[pre][a][b][x] + A[i]  ) ;                        dp[now][a][b][x] = max(dp[now][a][b][x] , dp[pre][a][b][x] ) ;                        dp[now][a][k-1][x+1] = max(dp[now][a][k-1][x+1] , dp[pre][a][b][x] + B[i] ) ;                    }                    else if(a != 0 && b != 0)                    {                        dp[now][(a-1)][ k - 1][x +1] = max(dp[now][(a - 1)][k-1][x+1], dp[pre][a][b][x] + ((A[i]) || (B[i])));                        dp[now][a-1][b-1][x] = max(dp[now][a-1][b-1][x] , dp[pre][a][b][x]  + (A[i] || B[i])) ;                        dp[now][k-1][b-1][x+1] = max(dp[now][k-1][b-1][x+1] , dp[pre][a][b][x] + ( A[i] || B[i]) ) ;                    }                    else if(a!= 0 && b == 0)                    {                        dp[now][a-1][b][x] = max(dp[now][a-1][b][x] , dp[pre][a][b][x] + A[i]) ;                        dp[now][a-1][k- 1][x+1] = max(dp[now][a-1][k-1][x+1] , dp[pre][a][b][x] + (A[i] | B[i])) ;                        dp[now][k-1][b][x + 1] = max(dp[now][k-1][b][x+1] , dp[pre][a][b][x] + A[i] ) ;                    }                }            }        }        clr2(dp[pre]) ;        now ^= 1 ;        pre ^= 1;    }    for(int i = 0 ; i <= p ; ++ i)    {        for(int a = 0 ; a <= k ; ++ a)            for(int b = 0 ; b <= k ; ++ b)ans = max(ans , dp[pre][a][b][i]) ;    }    cout<<ans <<endl;}
2 0
原创粉丝点击