zoukankan      html  css  js  c++  java
  • 日照学习提高班day3测试

    A

         

      

    思路:

      一看到'#''.'什么的就想到搜索怪我怪我。。。

      这道题勉强说是搜索别打我qwq

      1)因为不重复,所以首先要判断是否%5==0,若不满足,直接输出NO

      2)弄个vis数组记录是否被搜过,如果该处是‘#’并且没有被搜索过,就搜索他正下,左下,右下,以及下下是否都为#,若不是,输出NO

      3)如果是就进行标记(5个点都进行标记,因为只能使用一次),最终如果成功的渡劫,输出YES

    坑点:

      搜索下方是x+1而不是x-1(吃亏了qwq)

    上代码:

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    int n,cnt,tot;
    char w[110][110];
    bool vis[110][110];
    int dx[4] = {0, 0,1,-1},
        dy[4] = {1,-1,0, 0};
    
    bool check(int x,int y)
    {
        if(x>n || x<1 || y>n || y<1 || vis[x][y])
            return false;
        return true;
    }
    
    void dfs(int x,int y)
    {
        for(int i=0;i<4;++i)
        {
            int xx=x+dx[i],yy=y+dy[i];
            if(!check(xx,yy))
                continue;
            if(w[xx][yy]=='#')
                tot++;
        }
    }
    
    void dfs2(int x,int y)
    {
        for(int i=0;i<4;++i)
        {
            int xx=x+dx[i],yy=y+dy[i];
            vis[xx][yy]=true;
        }
    }
    
    bool orz(int x,int y)
    {
        vis[x+1][y]=true;
        tot=0;
        dfs(x+1,y);
        if(tot==4)
        {
            dfs2(x+1,y);
            return true;
        }
        return false;
    }
    
    int main()
    {
        freopen("puzzle.in","r",stdin);
        freopen("puzzle.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%s",w[i]+1);
            for(int j=1;j<=n;++j)
                if(w[i][j]=='#')
                    ++cnt;
        }
        if(cnt%5)
        {
            printf("NO");
            return 0;
        }
        else if(!cnt)
        {
            printf("YES");
            return 0;
        }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                if(w[i][j]=='#' && !vis[i][j])
                {
                    if(!orz(i,j))
                    {
                        printf("NO");
                        return 0;
                    }
                }
        printf("YES");
        return 0;
    }

     

    思路:

      题目大整容!!!

      luoguP2816宋荣子搭积木

      贪心。

      1)先将所有的盒子按照承载量从小到大排序

      2)然后我们开一个数组,记录一下当前一共有多少列,每一列一共有多少个盒子。

      3)接着从小到大扫描所有的盒子,找到能放下的数量最多的列,把它放进去。

      4)如果没有任何一列能放下,则建一个新列。

    上代码:

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    const int Maxn = 5e3 + 233;
    int n,tot;
    int a[Maxn],b[Maxn];
    
    inline void works()
    {
        for(int i=1;i<=n;++i)
            if(!tot)///创造新列
                b[++tot]=1;
            else {///Maxx用来记录上面放了多少块积木
                int Maxx=0,flag=0;
                for(int j=1;j<=tot;++j)
                    if(a[i]>=b[j] && b[j]>Maxx)
                        Maxx=b[j],flag=j;
                if(!flag)///若积木不高兴了
                    b[++tot]=1;///再建一个列
                else///装入该列
                    b[flag]++;
            }
        cout<<tot;
    }
    
    int main()
    {
        freopen("box.in","r",stdin);
        freopen("box.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
            scanf("%d",&a[i]);
        sort(a+1,a+1+n);///记住一定要进行排序!!毕竟贪心嘛,,,
        works();
        return 0;
    }

    C

     

    思路:

      题目大整容!

      luoguP1525关押罪犯

      三种做法

      1)普通并查集:

         i表示第i个学生,i+n为虚拟节点,表示不能和i在一个宿舍的人

        若两个点在同一并查集中,说明它们必须被分到同一个宿舍楼

        然后将所有的爱慕关系从大到小排序

        若a和b在同一并查集中,则此时c为答案

        若不在同一并查集,令a与b+n所在并查集合并,b与a+n所在并查集合并

      2)加权并查集:

        同样将所有爱慕关系从大到小排序

        每个点存储额外信息type,type为0表示和父亲结点在同一个宿舍楼,1表示和父亲结点不在同一个宿舍楼

        合并与查询的方式类似食物链

      3)二分+dfs(二分图染色问题):

        二分答案

        对于比二分答案大的爱慕关系,建图,

        显然若该图可以黑白染色,该答案可行,反之不可行

    上代码:

     给出普通并查集做法以及二分图做法~

    ①普通并查集做法

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    int n,m,dad[40010];
    
    struct node {
        int a,b,c;
        bool operator < (const node &qwq)const
        {///重载运算符 
            return c > qwq.c;
        }
    }e[100010];
    
    int getdad(int x)
    {return x == dad[x] ? x : dad[x]=getdad(dad[x]);}
    
    int main()
    {
        freopen("love.in","r",stdin);
        freopen("love.out","w",stdout);
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n*2;i++)
            dad[i]=i;///构建虚拟点 
        for(int i=1;i<=m;i++)
           scanf("%d %d %d",&e[i].a,&e[i].b,&e[i].c);
        sort(e+1,e+1+m);
        for(int i=1;i<=m;i++)
        {
            int f1=getdad(e[i].a),f2=getdad(e[i].b);
            if(f1==f2)
            {
                printf("%d",e[i].c);
                return 0;
            }
            ///与虚拟点进行合并,表示不再一个宿舍中 
            dad[f1]=getdad(e[i].b+n);///将f1与 b的补集合并
            dad[f2]=getdad(e[i].a+n);///将f2与 a的补集合并
        }
        ///若合法: 
        printf("0");
        return 0;
    }

     ②二分图做法

    #include <iostream>
    #include <cstdio>
    #include <algorithm> 
    #include <cstring>
    using namespace std;
    
    const int N = 20001, M = 100001;
    int n,m,ans;
    int W,w[M],col[N];
    struct node {
        int w,to,next;
    }e[M<<1];
    int top,head[N];
    void add(int u,int v,int w) {
        top++;
        e[top].w=w;
        e[top].to=v;
        e[top].next=head[u];
        head[u]=top;
    }
    
    bool dfs(int u,int c) {
        for(int i=head[u],v,w; i; i=e[i].next) {
            w=e[i].w;
            if(w<=W) continue;
            v=e[i].to;
            if(col[u]==col[v]) return false;
            if(!col[v]) {
                col[v]=3-c;
                if(!dfs(v,col[v])) return false;
            }
        }
        return true;
    }
    
    bool check() {
        memset(col,0,sizeof(col));
        for(int i=1; i<=n; i++)
            if(!col[i]) {
                col[i]=1;
                if(!dfs(i,1)) return false;
            }
        return true;
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        for(int i=1,a,b,c; i<=m; i++) {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c),add(b,a,c);
            w[i]=c;
        }
        sort(w+1,w+1+m);
        int l=1,r=m,mid;
        while(l<=r) {
            mid=(l+r)>>1;
            W=w[mid];
            if(check()) ans=w[mid],r=mid-1;
            else l=mid+1;
        }
        if(l==1 && r<l) cout<<"0";
        else printf("%d",ans);
        return 0;
    }

     

    如果运气好也是错,那我倒愿意错上加错!

    ❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀

  • 相关阅读:
    看代码写程序
    NP
    一道神题
    找平方数
    凝视
    排队打水
    时间计算
    git客户端下载地址
    iOS GCD
    UIView 和 CALayer的那点事
  • 原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/7252450.html
Copyright © 2011-2022 走看看