2018美团CodeM 题解

2018美团CodeM 题解

我现场打了3题,看看稳进复赛,就不打了。

T1

这题很简单,先扫一趟刷出最大值,标记最大值出现的时候,然后在扫一遍输出答案,这样效率高。

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,k,MAXT,Now,hsh[505][505],ans[505][505],ID;
struct xcw{
    int x,y,z;double t;
    bool operator <(const xcw b)const{return t<b.t;}
}a[100005];
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;i++){
        int x,y,z,h,m;double s;
        scanf("%d%d%d%d:%d:%lf",&x,&y,&z,&h,&m,&s);
        a[i]=(xcw){x,y,z,s+(double)h*3600+(double)m*60};
    }
    sort(a+1,a+1+k);
    for(int i=1;i<=k;i++){
        if(a[i].z==0){
            if(hsh[a[i].x][a[i].y]==0) Now++;
            hsh[a[i].x][a[i].y]++;
        }else{
            if(hsh[a[i].x][a[i].y]==1) Now--;
            hsh[a[i].x][a[i].y]--;
        }
        if(Now>=MAXT) MAXT=Now,ID=i;
    }
    memset(hsh,0,sizeof(hsh));
    for(int i=1;i<=ID;i++)
    if(a[i].z==0) hsh[a[i].x][a[i].y]++;
    else hsh[a[i].x][a[i].y]--;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++) printf(j==m?"%d\n":"%d",hsh[i][j]>0);
    return 0;
}

T2

这题我没打,但是我们机房XYZ dalao打掉了此题(卡在95%一个小时一直过不了,最后发现-1没判),他的想法就是DP,我没有仔细问。

T3

这题其实不难,首先我们知道l=1时最优,这个好证,那么r怎么办,其实也不难,推一下就知道了,最高位与n的最高位相同,然后在不大于n的情况下1越多越好。这个推出来了,那么就简单了。

代码如下:

#include<cstdio>
#include<cstring>
using namespace std;
int n,Ans,Len;
char ch[20005];
int main(){
    #ifndef ONLINE_JUDGE
    freopen("T3.in","r",stdin);
    freopen("T3.out","w",stdout);
    #endif
    gets(ch+1);Len=strlen(ch+1);
    for(int i=2;i<=Len;i++){
        if(ch[i]=='1'){
            bool t=1;
            for(int j=i+1;j<=Len;j++) if(ch[j]=='0'){t=0;break;}
            if(!t){
                ch[i]='0';
                for(int j=i+1;j<=Len;j++) ch[j]='1';
            }
            break;
        }
    }
    for(int i=1;i<=Len;i++) Ans+=(ch[i]=='1');
    for(int i=3;i<=Len;i++) Ans+=i-1;
    printf("%d\n",Ans);
    return 0;
}

T4

平面几何题,我们会发现这个答案是一个单峰函数,那么果断三分,但是我不会QAQ。我就讲讲我的另一个暴力的想法。
这里写图片描述
R是已知的,我们只需要枚举D,就能确定这个圆上的点,如果每次D+=1e-6的话,肯定超时,我们知道这是单峰函数,那么我们就枚举 Δ x 表示D每次的增量,我们想让答案越精确,那么 Δ x 就得越小。
答案Ans的值Just like this:
这里写图片描述
每次去求当长度等于 D 的答案和 Δ D 的答案,如果当前出现这种情况,那么答案就在 D D + Δ x 之间,那么就将 Δ x 减小,继续找。我选择每次除以1000,然后精度定在1e-9,所以这个算法的复杂度就是O(4*1000)。
我的表达不太好,所以还不懂的只能看代码了。

代码如下:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int f[4][2]={{1,1},{-1,1},{1,-1},{-1,-1}};
double R,L,Lst,rx1,rx2,ry1,ry2,x,_x,y,_y,Ans=1e99;
double Check(double D){
    double xx,yy,_xx,_yy;
    xx=D,yy=sqrt(R*R-D*D);_xx=-D,_yy=-yy;
    return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy))+sqrt((_x-_xx)*(_x-_xx)+(_y-_yy)*(_y-_yy));
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("T4.in","r",stdin);
    freopen("T4.out","w",stdout);
    #endif
    scanf("%lf%lf%lf%lf%lf",&R,&rx1,&ry1,&rx2,&ry2);
    for(int i=0;i<4;i++){//我感觉这个函数有两个峰,因为时间关系,没有去证,直接旋转这个圆来求解。 
        x=rx1*f[i][0];y=ry1*f[i][1];
        _x=rx2*f[i][0];_y=ry2*f[i][1];
        Lst=Check(-R);L=R;
        for(double D=-L+1;D<=L;D+=1){
            double Now=Check(D);
            if(Lst<=Now){L=D-1;break;}
            Lst=Now;
        }
        Lst=Check(L);
        for(double D=L+(1e-3);D<=L+1;D+=1e-3){
            double Now=Check(D);
            if(Lst<=Now){L=D-(1e-3);break;}
            Lst=Now;
        }
        Lst=Check(L);
        for(double D=L+(1e-6);D<=L+(1e-3);D+=1e-6){
            double Now=Check(D);
            if(Lst<=Now){L=D-(1e-6);break;}
            Lst=Now;
        }
        Lst=Check(L);
        for(double D=L+(1e-9);D<=L+(1e-6);D+=1e-9){
            double Now=Check(D);
            if(Lst<=Now){L=D-(1e-9);break;}
            Lst=Now;
        }
        Ans=min(Ans,Check(L));
    }
    Ans=min(Ans,sqrt((rx1-rx2)*(rx1-rx2)+(ry1-ry2)*(ry1-ry2)));
    printf("%.10lf",Ans);
    return 0;
}

T5~T6

题目没来的及看。

猜你喜欢

转载自blog.csdn.net/qq_41357771/article/details/80788064
今日推荐