zoukankan      html  css  js  c++  java
  • 实验舱比赛19.3.10

    A.prince

    http://noi.ac/problem/242

    题解:这道题80分的普通dp显然是秒切,但是要注意的是运算符的优先级,可能由于优先级造成问题。然后这类的进制问题要考虑每个数和二进制位的关系,所以可以想到对于每个进制位进行考虑,对于每个数,可以得到的最大贡献就是f[i]+1(1<<i&x)max,然后对于每个可行的进制位再回去看是否可以更新答案

    错误:要注意进制从0开始

    代码:

    //80分作法 
    /*#include<iostream>
    #include<cstdio> 
    #include<cstdlib>
    using namespace std;
    int d[1010101],b[1010101];//dp转移 
    int ans=1,n;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&d[i]);
        b[1]=1;
        for(int i=2;i<=n;i++){
            b[i]=1;
            for(int j=1;j<i;j++)
                if((d[i]&d[j])!=0)//wrong要注意运算符顺序 
                    b[i]=max(b[i],b[j]+1);
        
        }
        for(int i=1;i<=n;i++)ans=max(ans,b[i]);
        printf("%d",ans);
        return 0;
    }*/ 
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int f[40],n,te;
    int main(){
        scanf("%d",&n);
        int x;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            te=1;
            for(int j=0;j<=30;j++)
                if((1<<j)&x)te=max(te,f[j]+1);
            for(int j=0;j<=30;j++)
                if((1<<j)&x)f[j]=max(te,f[j]);
        }
        int ans=0;
        for(int i=1;i<=30;i++)ans=max(ans,f[i]);
        printf("%d",ans);
        return 0;
    }
    View Code

    B.toy

    http://noi.ac/problem/243

    题解:这道题初读会感到害怕,但是这类题最好手推感受一下,由于我们知道每三个格子中有几个,所以可以知二推一(可以假设第0个格子为0,因为第二列第一个对应的正好就是0,1,2),所以我们只要考虑1的情况就可得到2,然后得到所有格子,所以可以发现最多就两种情况,我们分别枚举第1个格子为0或1的情况,就可以得出其他格子是否有物品,判断其是否只有0或一个,且第n+1个格子为0,若其中任意不满足就说明这种方法不可行

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int a[10101],b[10101];//b表示是否有放
    int ans=2,n;
    void check(){
        for(int i=2;i<=n+1;i++){
            b[i]=a[i-1]-b[i-1]-b[i-2];
            if(b[i]!=0&&b[i]!=1){ans--;break;}
            if(i==n+1&&b[i]!=0){ans--;break;}
        }
    } 
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        b[1]=0;
        check();
        b[1]=1;
        check();
        printf("%d",ans);
        return 0;
    }
    View Code

    C.product

    http://noi.ac/problem/244

    题解:首先考虑贪心,因为要求的是个数多,所以一定是从小到大排序,然后取越多越好,所以考虑二分答案取前p个,于是将题目转化为一道搜索题(n<=50暗示搜索),来判定是否可以取完前p个,但是要注意要从大到小判断,因为我们判断的是全部是否都可以,所以如果先满足小的,被截掉之后可能无法满足大的。显然要考虑剪枝,第一枝可行性剪枝,如果拥有的全部长度减去不能用的(进过裁剪导致剩下的比第一个还小),第二支如果前一个和现在的一样大(正常要小),那么要从现在找到的这个开始枚举较优

    错误:是否成立是有多条路径只要一条成立就好了,而不是一条路不成立就全不成立,所以不要贪懒

             要注意边界的设置,有限制范围的不能乱定,否则会加大范围(为空的部分也算进去了)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int m,n;
    int offer[1010],need[1010];
    int used[1010];
    int ans;
    int waste,so,sn;
    int dfs(int x,int la){//la进行剪枝,如果两个长度相等,一定要从现在这个开始 
        if(x<1)return true;
        if(so-waste<sn)return false;
        for(int i=la;i<=m;i++){
            if(used[i]>=need[x]){
                used[i]-=need[x];
                if(used[i]<need[1])waste+=used[i];//剩下的不能用了 
                if(need[x]==need[x-1]) {if(dfs(x-1,i))return true;}//wrong
                else {if(dfs(x-1,1))return true;}
                if(used[i]<need[1])waste-=used[i];
                used[i]+=need[x];
            }
        }
        return false;
    }
    int main(){
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d",&offer[i]);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&need[i]);
        sort(offer+1,offer+1+m);
        sort(need+1,need+1+n);
        int l=1,r=n;//wrong
        while(l<=r){//判断前p个是否能被完全拆开 
            int mid=(l+r)/2;
            waste=so=sn=0;//优化
            for(int i=1;i<=mid;i++)sn+=need[i];
            for(int i=1;i<=m;i++)so+=offer[i],used[i]=offer[i]; 
            if(dfs(mid,1)){
                ans=mid,l=mid+1;
            }
            else r=mid-1;
        }
        printf("%d",ans);
    }
    View Code
  • 相关阅读:
    Leetcode 148. Sort List
    stat/lstat函数使用
    C/C++内存分配和管理
    initializer_list 列表初始化
    extern "C" 含义
    C语言宏定义##连接符和#符的使用
    rabbitMQ日常管理(转)
    java/rabbitmp发布订阅示例(转)
    oracle分页查询
    oracle imp使用
  • 原文地址:https://www.cnblogs.com/linzeli/p/10551279.html
Copyright © 2011-2022 走看看