校内模拟神光

Posted yjkhhh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了校内模拟神光相关的知识,希望对你有一定的参考价值。

技术分享图片

技术分享图片

看到(“L 的最小值”),很容易想到二分答案,那么这道题的关键就是如何快速地检验

首先,如果已经规定了操作顺序,我们可以(O(n))贪心求解

但是要枚举顺序的话复杂度是阶乘级别的,显然布星

于是考虑(DP),我一开始的(DP)状态:(dp[i][j])表示干掉前(i)(fa)坛,用(j)次红光时的最少用多少次绿光

发现转移有些麻烦,又因为时间不大够了,我就随机操作顺序+贪心(100)次了(骗到(60)分)

题解的做法:

(dp[i][j]表示用i次color{green}{绿光}和j次color{red}{红光}最多摧毁从1开始多少个连续的法坛)

转移就是

[dp[i][j]=P[dp[i-1][j]+1]+Q[dp[i][j-1]+1]]

其中(P[k])表示从第(k)个法坛开始向右(L)长度内有多少法坛,(Q[k])表示从第(k)个法坛开始向右(2L)长度内有多少法坛,都可以在(DP)前预处理出来

(60)分随机算法:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<ctime>
using namespace std;
const int N=2010;
int n,r,g,a[N];
inline bool check(int l){
    int t=100;
    while(t--){
        int tot1=0,tot2=0,dr=0;
        for(int i=1;i<=n;i++){
            if(a[i]<dr) continue;
            if((rand()%2||tot2==g)&&tot1!=r){
                dr=a[i]+l-1; ++tot1;
                if(dr>a[n]) return 1;
            }
            else if(tot2!=g){
                dr=a[i]+l+l-1; ++tot2;
                if(dr>a[n]) return 1;
            }
            else break;
        }
        if(dr>a[n]) return 1;
    }
    return 0;
}
int main()
{
    srand(19260817+time(NULL));
    freopen("light.in","r",stdin);
    freopen("light.out","w",stdout);
    scanf("%d%d%d",&n,&r,&g);
    if(r+g>=n){
        puts("1");
        return 0;
    }
    for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    int l=1,r=1000000000;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    printf("%d
",l);
    fclose(stdin); fclose(stdout);
    return 0;
}

(100)分代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 2010
#define reset(a) memset(a,0,sizeof(a))
int n,r,g,a[N],dp[N][N];
int P[N],Q[N];
bool check(int L)
{
    reset(P),reset(Q),reset(dp);
    for(int i=1;i<=n;i++){
        int j=i;
        while(a[j]<=a[i]+L-1&&j<=n) ++j;
        P[i]=j-1;
        while(a[j]<=a[i]+L+L-1&&j<=n) ++j;
        Q[i]=j-1;
    }
    P[n+1]=Q[n+1]=n;
    for(int i=0;i<=r;i++)
     for(int j=0;j<=g;j++){
        if(i) dp[i][j]=max(dp[i][j],P[dp[i-1][j]+1]);
        if(j) dp[i][j]=max(dp[i][j],Q[dp[i][j-1]+1]);
    }
    return dp[r][g]==n;
}
int main()
{
    freopen("light.in","r",stdin);
    freopen("light.out","w",stdout);
    scanf("%d%d%d",&n,&r,&g);
    if(r+g>=n){
        puts("1");
        return 0;
    }
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    int l=1,r=1e9;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    printf("%d
",l);
    fclose(stdin); fclose(stdout);
    return 0;
}

以上是关于校内模拟神光的主要内容,如果未能解决你的问题,请参考以下文章

校内模拟赛T1大美江湖

2017-9-3 校内模拟T2取数win

校内模拟赛 虫洞(by NiroBC)

2017.6.11 校内模拟赛

httpClient模拟登陆校内某系统

校内模拟考