zoukankan      html  css  js  c++  java
  • 网易2018.03.27算法岗,三道编程题100%样例AC题解

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~
    http://www.cnblogs.com/chenxiwenruo/p/8660814.html
    特别不喜欢那些随便转载别人的原创文章又不给出链接的
    所以不准偷偷复制博主的博客噢~~

    1. 自定义排序

       第一题是第一行给出n(1<=n<=100),表示下面有n行,每行A(0<=A<24)和B(0<=B<60),表示定的闹钟为AhBmin。

       接下来给定X,表示小明从起床到教室需要X分钟,最后一行给出A(0<=A<24)和B(0<=B<60)表示上课时间AhBmin。

       求问小明赶在上课前,能够定的最晚闹铃时间为多少,样例保证必定有一个符合要求。

     

     对闹铃排序,按照A从小到大排序,当A相同的时候,B从小到大排序,然后从最后一个往回遍历,找到距离上课时间>=Xmin中的闹铃时间,输出即可。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <string.h>
    /*
    3
    5 0
    6 0
    7 0
    59
    6 59
    */
    using namespace std;
    const int maxn=105;
    struct Node{
        int h;
        int m;
        bool operator<(const Node tmp)const{
            if(h==tmp.h)
                return m<tmp.m;
            else
                return h<tmp.h;
        }
    };
    Node clocks[maxn];
    int n;
    int main()
    {
        int a,b;
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d %d",&clocks[i].h,&clocks[i].m);
        }
        sort(clocks,clocks+n);
        int x;
        scanf("%d",&x);
        scanf("%d %d",&a,&b);
        for(int i=n-1;i>=0;i--){
            if(clocks[i].h>a)
                continue;
            if(clocks[i].h==a){
                if(b-clocks[i].m>=x){
                    printf("%d %d
    ",clocks[i].h,clocks[i].m);
                    break;
                }
            }
            else{
                if(60-clocks[i].m+(a-clocks[i].h-1)*60+b>=x){
                    printf("%d %d
    ",clocks[i].h,clocks[i].m);
                    break;
                }
            }
        }
    
        return 0;
    }
    View Code

    2. 离散化+二分查找

       对于一个矩阵,在坐标系内,左下角坐标(x1,y1),右上角坐标(x2,y2),现在给出n个矩阵的坐标,问重叠区域矩阵最多的个数?如果没有矩阵重叠,输出1。

       输入样例,第一行n,接下来分别为n个x1,n个y1,n个x2,n个y2。1<=n<=50,-10^9<=xi,yi<=10^9。

       

       很明显,n的范围只有50,数据量很小,但是x和y很大,需要离散化处理,这样的话最多200个不同的值。

       处理之后,对于第i个矩阵,遍历它所在的范围,cnt[i][j]++即可。最后输出cnt最大的那个。如果cnt都为0,即没有矩阵,也就没有重叠,也输出1。

       这里注意,一开始我在遍历的时候,下面for循环,起始条件没有+1,这样的话还有10%样例是过不了的。应该是统计边,而不是统计点,因为对于[(0,0),(0,0)]是构不成矩阵的。

    for(int k=lx+1;k<=rx;k++){
            for(int p=ly+1;p<=ry;p++){
                    cnt[k][p]++;
            }
    }

    完整代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <string.h>
    using namespace std;
    /*
    2
    0 90
    0 90
    100 200
    100 200
    */
    const int maxn=205;
    int n;
    int xx1[maxn],xx2[maxn],yy1[maxn],yy2[maxn];
    int idx=0;
    int a[maxn];
    int hash_x[maxn];
    int cnt[maxn][maxn];
    
    int binarySearch(int *a,int t,int n){
        int l=0,r=n-1;
        int mid;
        while(l<=r){
            mid=(l+r)>>1;
            if(a[mid]==t)
                return mid;
            if(t<a[mid])
                r=mid-1;
            else
                l=mid+1;
        }
        return -1;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d",&xx1[i]);
            a[i*4+0]=xx1[i];
        }
        for(int i=0;i<n;i++){
            scanf("%d",&yy1[i]);
            a[i*4+1]=yy1[i];
        }
        for(int i=0;i<n;i++){
            scanf("%d",&xx2[i]);
            a[i*4+2]=xx2[i];
        }
        for(int i=0;i<n;i++){
            scanf("%d",&yy2[i]);
            a[i*4+3]=yy2[i];
        }
        //离散化,将-10^9~10^9的数据映射为0~200以内,因为最多出现4*50不同的数,映射值即为索引。
        sort(a,a+4*n);
        hash_x[0]=a[0];
        idx=1;
        for(int i=1;i<4*n;i++){
            if(a[i]!=a[i-1]){
                hash_x[idx]=a[i];
                idx++;
            }
        }
        memset(cnt,0,sizeof(cnt));
        for(int i=0;i<n;i++){
            int lx,ly,rx,ry;
            //二分查找对应离散化后的索引。
            lx=binarySearch(hash_x,xx1[i],idx);
            ly=binarySearch(hash_x,yy1[i],idx);
            rx=binarySearch(hash_x,xx2[i],idx);
            ry=binarySearch(hash_x,yy2[i],idx);
            for(int k=lx+1;k<=rx;k++){
                for(int p=ly+1;p<=ry;p++){
                    cnt[k][p]++;
                }
            }
        }
        int ans=0;
        for(int i=0;i<=idx;i++){
            for(int j=0;j<=idx;j++){
                ans=max(ans,cnt[i][j]);
            }
        }
        if(ans==0)
            ans=1;
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    3. dfs+剪枝

       第一行n和w,接下来有n个零食的重量v[i],0<v[i]<10^9,问你在背包重量为w的情况下,最多能有几种装法?背包重量为0也算一种。

       比如说

       3 8

       1 2 3

       因为总的背包容量大于三个总重量,所以三个每个都可选可不选,共计2^3种。

       

        先对零食的重量从小到大排序,然后从最后一个开始,零食索引为idx,背包剩余容量为left,现有方案总数为tot,初始为0。

        1. 若idx<=0或者left<=0,表示没得选了,只有就这一种方案,所以tot++即可。

        2. 若idx之前所有零食的总重量<=left,那么很显然,该方案数总共为2^idx,加到tot上即可。

        3. 若v[idx]<=left,那么我可以放第idx个零食,方案数即为dfs(idx-1,left-v[idx])。

        4. 当然不管怎样,我也可以选择不放第idx个零食,方案数即为dfs(idx-1,left)。

        注意,因为零食重量的范围,所以代码里的two数组、sum数组、tot为long long,才不会溢出,否则样例会有不过。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <string.h>
    using namespace std;
    const int maxn=35;
    int n;
    int v[maxn];
    long long sum[maxn]; //sum[i]统计v[1]~v[i]的和
    int w;
    long long tot=0;
    long long two[31]; //two[i]即为2^i值
    
    //dfs搜索所有的方案数
    void dfs(int idx,int left){
        if(idx<=0 || left<=0){
            tot+=1;
            return;
        }
        if(sum[idx]<=left){
            tot+=two[idx];
            return;
        }
        if(left>=v[idx]){
            dfs(idx-1,left-v[idx]);
        }
        dfs(idx-1,left);
    }
    int main()
    {
        two[0]=1;
        for(int i=1;i<=31;i++)
            two[i]=two[i-1]*2;
        scanf("%d %d",&n,&w);
        for(int i=1;i<=n;i++){
            scanf("%d",&v[i]);
        }
        sort(v+1,v+n+1);
        sum[0]=0;
        for(int i=1;i<=n;i++){
            sum[i]=sum[i-1]+v[i];
        }
        dfs(n,w);
        printf("%lld
    ",tot);
        return 0;
    }
    View Code

        

           

  • 相关阅读:
    Android Loader异步装载
    Android 清除本地缓存
    Android 小知识
    Android 百度地图用法
    ANDROID笔记:四大组件之广播
    Android扩展:一个自动findViewById的小工具
    ANDROID笔记:基于handle的异步请求网络数据的一种方法
    ANDROID笔记:多线程断点下载
    ANDROID笔记:AIDL介绍
    ANDROID笔记:activity通过ContentProvider传值(仿调用系统图片浏览器过程)
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/8660814.html
Copyright © 2011-2022 走看看