zoukankan      html  css  js  c++  java
  • 9.17模拟赛

    T1 巧克力棒

    题目描述

    LYK 找到了一根巧克力棒,但是这根巧克力棒太长了,LYK 无法一口吞进去。

    具体地,这根巧克力棒长为nn,它想将这根巧克力棒折成nn段长为11的巧克力棒,然后慢慢享用。

    它打算每次将一根长为kk的巧克力棒折成两段长为aa和bb的巧克力棒,此时若a=ba=b,则LYK 觉得它完成了一件非常困难的事,并会得到11点成就感。

    LYK 想知道一根长度为nn的巧克力棒能使它得到最多几点成就感。

    输入输出格式

    输入格式:

     

    第一行一个数nn。

     

    输出格式:

     

    一个数表示答案。

     

    输入输出样例

    输入样例#1:
    7
    输出样例#1:
    4

    说明

    对于20\%20%的数据,n leq 5n5。

    对于50\%50%的数据,n leq 20n20。

    对于80\%80%的数据,n leq 2000n2000。

    对于100\%100%的数据,n leq 1000000000n1000000000。

    样例解释

    77掰成3+43+4, 将33掰成1+21+2, 将44掰成2+22+2获得11点成就感, 将剩下的所有22掰成 1+11+1

    获得33点成就感。总共44点成就感。

    题解:

    考试80分dp,计算局部最优值 枚举断点取最大

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,f[2017];
    int main(){
        freopen("chocolate.in","r",stdin);
        freopen("chocolate.out","w",stdout);
        scanf("%d",&n);
        f[1]=0;f[2]=1;f[3]=1;
        for(int i=4;i<=n;i++){
            for(int j=0;j<=i;j++){
                f[i]=max(f[i],f[j]+f[i-j]);
            }
            if(i%2==0)f[i]=max(f[i],f[i/2]*2+1);
        }
        printf("%d
    ",f[n]);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    正解:贪心

    发现最后肯定分成n个长度为1,要求有贡献,那么长度为1的一定是由长度为2的分来的,分成长度为2 想要有贡献 必须从长度为4分来的,分成

    长度为4想要有贡献 必须分成长度为8的.....所以将巧克力棒分成2^k得到的结果更优。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long n,ans,js;
    void dfs(long long n){
        if(n==1||n==0)return;
        long long i;
        for( i=1;i*2<=n;i*=2);
        ans+=i-1;
        dfs(n-i);
    }
    int main(){
        scanf("%lld",&n);
        dfs(n);
        cout<<ans<<endl;
        return 0;
    }

    T2 LYK 快跑!

    题目描述

    LYK 陷进了一个迷宫! 这个迷宫是网格图形状的。 LYK 一开始在(1,1)(1,1)位置, 出口在(n,m)(n,m)。

    而且这个迷宫里有很多怪兽,若第aa行第bb列有一个怪兽,且此时 LYK 处于第 cc行dd列,此时这个怪兽对它的威胁程度为|a-c|+|b-d|ac+bd∣。 LYK 想找到一条路径,使得它能从(1,1)(1,1)到达(n,m)(n,m),且在途中对它威胁程度最小的怪兽的威胁程度尽可能大。

    当然若起点或者终点处有怪兽时,无论路径长什么样,威胁程度最小的怪兽始终=0=0。

    输入输出格式

    输入格式:

     

    第一行两个数n,mn,m。

    接下来nn行,每行mm个数,如果该数为00,则表示该位置没有怪兽,否则存在怪兽。

    数据保证至少存在一个怪兽。

     

    输出格式:

     

    一个数表示答案。

     

    输入输出样例

    输入样例#1:
    3 4
    0 1 1 0
    0 0 0 0
    1 1 1 0
    输出样例#1:
    1

    说明

    对于20\%20%的数据n=1n=1。

    对于40\%40%的数据n leq 2n2。

    对于60\%60%的数据n,m leq 10n,m10。

    对于80\%80%的数据n,m leq100n,m100。

    对于90\%90%的数据n,m leq 1000n,m1000。

    对于另外10\%10%的数据n,m leq 1000n,m1000且怪兽数量leq 100100。

    题目大意:要求从(1,1)-->(n,m)的路径中距离最小的怪兽的距离最大值

    题解:题目描述最小值最大应该是二分...可是我没想出来...

    40搜索....(吐槽:只有40分不该呀.....

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    int n,m,cnt,ans,js;
    int map[102][102],vis[102][102];
    int mx[4]={0,1,0,-1},
        my[4]={1,0,-1,0};
        
    struct WW{
        int x,y;
    }w[10005];
    
    struct T{
        int x,y,minl;
    }s[50003];
    
    int zs(int x){
        if(x<0)return -x;
        return x;
    }
    
    void slove(){
        queue<T>q;T s;s.x=1;s.y=1;s.minl=0x7fffffff;
        q.push(s);
        while(!q.empty()){
            T now;
            now=q.front();q.pop();
            vis[now.x][now.y]=0;
            int minl=0x7ffffff;
            for(int i=1;i<=cnt;i++){
                int xx=w[i].x,yy=w[i].y;
                minl=min(minl,zs(xx-now.x)+zs(yy-now.y));
            }
            if(minl<now.minl)now.minl=minl;js++;
            cout<<now.x<<" "<<now.y<<"  "<<now.minl<<endl;
            if(js==10){
                exit(0);
            }
            if(now.x==n&&now.y==m)ans=max(ans,now.minl);
            for(int i=0;i<4;i++){
                int xx=now.x+mx[i],yy=now.y+my[i];
                if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]){
                    vis[xx][yy]=1;
                    q.push((T){xx,yy,now.minl});
                }
            }
        }
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int x;
                scanf("%d",&x);
                if(x)w[++cnt].x=i,w[cnt].y=j;
                if((i==1&&j==1&&x)||(i==n&&j==m&&x)||n==1){
                    printf("0
    ");
                    return 0;
                }
            }
        }
        slove();
        printf("%d
    ",ans);
        return 0;
    }

    正解:bfs预处理到每个非怪兽节点的最近的怪兽的距离,然后二分答案。

    队列要开大点

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,m,l,r,ans,map[1002][1002],vis[1002][1002],qx[1000000],qy[1000000],b[1002][1002];
    int mx[4]={0,1,-1,0},
        my[4]={1,0,0,-1};
    int head=1,tail;
    bool check(int limt){
        memset(vis,0,sizeof(vis));
        memset(qx,0,sizeof(qx));
        memset(qy,0,sizeof(qy));
        head=1;tail=0;
        qx[++tail]=1;qy[tail]=1;vis[1][1]=1;
        while(head<=tail){
            int nowx=qx[head],nowy=qy[head++];
            for(int i=0;i<4;i++){
                int xx=nowx+mx[i],yy=nowy+my[i];
                if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]&&b[xx][yy]>=limt){
                    qx[++tail]=xx;qy[tail]=yy;
                    vis[xx][yy]=1;
                }
            }
        }
        return vis[n][m];
    }
    void bfs(){
        while(head<=tail){
            int nowx=qx[head],nowy=qy[head++];
            for(int i=0;i<4;i++){
                int xx=nowx+mx[i],yy=nowy+my[i];
                if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]&&!b[xx][yy]&&!map[xx][yy]){
                    b[xx][yy]=b[nowx][nowy]+1;
                    vis[xx][yy]=1;
                    qx[++tail]=xx;qy[tail]=yy;
                }
            }
        }
        l=0;r=n*m;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid)){
                ans=mid;l=mid+1;
            }
            else r=mid-1;
        }
        printf("%d
    ",ans);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&map[i][j]);
                if(map[i][j]){
                    qx[++tail]=i;
                    qy[tail]=j;
                }
            }
        }
        if(map[1][1]||map[n][m]||n==1){
            printf("0
    ");
            return 0;
        }
        bfs();
        return 0;
    }

    T3 仙人掌(cactus)

    题目描述

    LYK 在冲刺清华集训(THUSC)于是它开始研究仙人掌,它想来和你一起分享它最近研究的结果。

    qwq

    如果在一个无向连通图中任意一条边至多属于一个简单环 (简单环的定义为每个点至多经过一次) ,且不存在自环,我们称这个图为仙人掌。

    LYK 觉得仙人掌还是太简单了,于是它定义了属于自己的仙人掌。

    定义一张图为美妙的仙人掌, 当且仅当这张图是一个仙人掌且对于任意两个不同的点i,ji,j,存在一条从ii出发到jj的路径,且经过的点的个数为|j-i|+1ji+1个。 给定一张nn个点mm条边且没有自环的图,LYK 想知道美妙的仙人掌最多有多少条边。

    数据保证整张图至少存在一个美妙的仙人掌。

    输入输出格式

    输入格式:

     

    第一行两个数n,mn,m表示这张图的点数和边数。

    接下来mm行,每行两个数u,vu,v表示存在一条连接u,vu,v的无向边。

     

    输出格式:

     

    一个数表示答案

     

    输入输出样例

    输入样例#1:
    4 6
    1 2
    1 3
    1 4
    2 3
    2 4
    3 4
    输出样例#1:
    4

    说明

    对于20\%20%的数据n leq 3n3。

    对于40\%40%的数据n leq 5n5。

    对于60\%60%的数据n leq 8n8。

    对于80\%80%的数据n leq 1000n1000。

    对于100\%100%的数据n leq 100000n100000且m leq min(200000,n*(n-1)/2)mmin(200000,n(n1)/2)。

    样例解释

    选择边1-212,1-313,2-323,3-434,能组成美妙的仙人掌,且不存在其它美妙仙人掌有超过44条边。

    题解:30骗分(就问你强不强...

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n;
    int main(){
        freopen("cactus.in","r",stdin);
        freopen("cactus.out","w",stdout);
        scanf("%d",&n);
        printf("%d
    ",n);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

     正解:由于i--j满足节点数等于|i-j|+1,那么i和i+1一定由一条边直接连着,剩下的边用线段覆盖解决。

    #include<cstdio>
    #include<algorithm>
    #define maxn 100010
    using namespace std;
    int n,m,cnt;
    struct node{
        int u,v;
        bool operator < (const node &x)const{
            return v<x.v;
        }
    }e[maxn*2];
    int init(){
        int x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    int main()
    {
        freopen("cactus.in","r",stdin);
        freopen("cactus.out","w",stdout);
        n=init();m=init();
        int u,v;
        for(int i=1;i<=m;i++){
            u=init();v=init();
            if(u>v)swap(u,v);
            if(u!=v-1){    
                e[++cnt].u=u;e[cnt].v=v;
            }
        }
        sort(e+1,e+1+cnt);
        int r=0,sum=0;
        for(int i=1;i<=cnt;i++)
            if(e[i].u>=r){
                sum++;r=e[i].v;
            }
        printf("%d
    ",sum+n-1);
        return 0;
    }
  • 相关阅读:
    Python 3学习 ——目录 Json Pickle
    Python 3 学习——函数扩展and迭代器生成器装饰器
    Python 3 学习——深浅拷贝以及函数
    Python 3 学习的第七小节——Linux-Ubuntu
    Python 3 —— 文件操作
    Python 3 学习的第五小节——字符编码与三级菜单实践
    关于PHP代码复用‘traits’的一段代码
    一个将对象彻底冻结的函数
    详解vue-cli脚手架项目-package.json
    关于element-ui日期选择器disabledDate使用心得
  • 原文地址:https://www.cnblogs.com/zzyh/p/7537755.html
Copyright © 2011-2022 走看看