zoukankan      html  css  js  c++  java
  • 【纪中受难记】——Day2.感觉冤的慌

    说实话,今天的题真的很简单。

    但是我……

    50/0/0/100。

    后来看看程序,发现是些很蠢的错误。。。还有没写的那些题,真的不难qwq


    1.佳肴:

    Description

      佳肴就是非常美味的菜的意思,佳肴最关键的是选择好原料。
      现在有N种原料,每种原料都有酸度S和苦度B两个属性,当选择多种原料时,总酸度为每种原料的酸度之积,总苦度为每种原料的苦度之和。
      正如大家所知,佳肴是既不酸也不苦的,因为要保证所选的原料使得总酸度和总苦度差的绝对值最小。
      由于佳肴不能只有水,所以必须至少选择一种佳肴。
     

    Input

      输入第一行包含一个整数N(1<=N<=10),表示原料的种数。
      接下来N行每行包含两个用一个空格隔开的整数,分别表示酸度和苦度。
      输入数据保证如果所有原料都选上,总酸度和总苦度不会超过10^9。

    Output

      输出总酸度和总苦度最小的差。

     

     

     

     

     

     

     

     

     

     

     

     

     

    这道题就是暴!搜!但是我起始点输了1,结果本来到了最后一组数据,当做越界处理了……

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n;
     4 int a[12],b[12],minans=1e9,ans[1000],tg[1000],cnt;
     5 void dfs(int k,int mul,int sum,int tag){
     6     if(k>n) return;
     7     ans[++cnt]=min(minans,abs(mul-sum));
     8     tg[cnt]=tag;
     9     dfs(k+1,mul*a[k+1],sum+b[k+1],1);
    10     dfs(k+1,mul,sum,tag);
    11 }
    12 int main(){
    13     scanf("%d",&n);
    14     int oans=1e9;
    15     for(int i=1;i<=n;i++){
    16         scanf("%d%d",&a[i],&b[i]);
    17         oans=min(oans,abs(a[i]-b[i]));
    18     } 
    19     dfs(0,1,0,0);
    20     for(int i=1;i<=cnt;i++){
    21         if(!tg[i]) continue;
    22         if(ans[i]<oans) oans=ans[i];
    23     }
    24     printf("%d\n",oans);
    25     return 0;
    26 }

    2.取数游戏

    Description

      Alice想让Bob陪他去看《唐山大地震》,但由于Bob是个很感性的人,怕流泪不想去,但又不好意思以这个作为拒绝的理由,便提出玩一个游戏。
      N个正整数围成一圈,规则如下:
      •两个玩家轮流取数;
      •最开始先手的玩家可以取任意一个数x;
      •从第二步开始当前玩家只能取x(上一玩家刚刚取的数)左右两边相邻的数;
      •直到取完所有的数,游戏结束;
      •取得较多奇数的玩家获胜。
      Bob为了显示大度,让Alice先取,但他忘了自己和Alice都是绝顶聪明之人,现在Alice请你帮他计算第一步有多少种取法使得最终获得胜利。
     

    Input

      第一行包含一个整数N(1<=N<=100),表示数的个数。第二行包含N个正整数,每个数都在1到1000之间,任意两个数互不相同。

    Output

      输出Alice第一步有多少种取法。

    这道题很精妙,当你先取下一个数字后,剩下的数字就可以展开变成一个序列,每次都从序列的两边取,就变成区间dp了。

    对于博弈论的题目,设置dp要考虑每个人都是天才,取到的都是最优解。

    设s[i][j]表示区间中奇数个数,f[i][j]表示先手取i或j能获得的最大奇数个数,

    f[i][j]=max(s[i][j]-f[i+1][j],s[i][j]-f[i][j-1]),转移方向从里到外,s用前缀和优化。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=110;
    int n;
    int a[N*2];
    int s[N*2];
    int f[N][N],ans;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            a[i]&=1;
        }
        for(int i=1;i<=n;i++){
            memset(f,0,sizeof(f));
            memset(s,0,sizeof(s));
            for(int j=1;j<=n;j++){
                s[j]=s[j-1]+a[j];
                f[j][j]=a[j];
            }
    //        for(int i=1;i<n;i++){
    //            for(int j=1;j+i<=n;j++){
    //                f[i][i+j]=max(s[i+j]-s[j-1]-f[j+1][i+j],s[i+j]-s[j-1]-f[j][i+j-1]);
    //            }
    //        }
            for(int k=1;k<=n-2;k++) { 
                for(int j=1;j+k<=n;j++) { 
                    int l=k+j; 
                    f[j][l]=max(s[l]-s[j-1]-f[j+1][l],s[l]-s[j-1]-f[j][l-1]); 
                } 
            } //
            f[1][n]=s[n]-f[2][n];
            if(s[n]/2+1<=f[1][n]) ans++;
            for(int i=0;i<=n;i++) a[i]=a[i+1];
            a[n]=a[0];
        }
        printf("%d\n",ans);
    //    for(int i=1;i<=n;i++){
    //        for(int j=1;j+i<=n*2;j++){
    //            f[j][j+i-1]=max(s[j+i]-s[j-1]-f[j+1][j+i-1],s[j+i]-s[j-1]-f[j][j+i-2]);
    //        }
    //    }
    //    for(int i=1;i<n;i++){
    //        for(int j=1;j+i<=n*2;j++){//l=j,r=j+i
    //            f[j][j+i]=max(s[j+i]-s[j-1]-f[j+1][j+i],s[j+i]-s[j-1]-f[j][j+i-1]); 
    //        }
    //    }
    //    for(int k = 1;k <= n - 2;k++) { 
    //            for(int j = 1;j <= 2*n - k;j++) { 
    //                int l = k + j; 
    //                f[j][l]=max(s[l]-s[j-1]-f[j+1][l],s[l]-s[j-1]-f[j][l-1]); 
    //            } 
    //    } 
    //    for(int i=1;i<=2*n;i++){
    //        cout<<a[i]<<" ";
    //    }
    //    for(int i=1;i<=2*n;i++){
    //        cout<<s[i]<<" ";
    //    }
    //    for(int i=1;i<=n;i++){
    //        if(s[i+n-1]-s[i-1]-f[i+1][i+n-1]>(n>>1)) ans++;
    //    }
    //    printf("%d",ans);
        
        return 0;
    }

    唯一一道不水的题目。

     

     

     


     

    3.删除

      这是道水题……但是当时没想到。

    Description

      Alice上化学课时又分心了,他首先画了一个3行N列的表格,然后把数字1到N填入表格的第一行,保证每个数只出现一次,另外两行他也填入数字1到N,但不限制每个数字的出现次数。
      Alice现在想删除若干列使得每一行排完序后完全一样,编程计算最少需要删除多少列。
     

    Input

      第一行包含一个整数N(1<=N<=100000),表示表格的列数。
      接下来三行每行包含N个整数,每个数在1到N之间,而且第一行的数互不相同。

    Output

      输出最少需要删除的列数。

     

     

     

     

     

     

      首先,对于一个表格,第二行和第三行不一定是全排列,就说明一定会有缺少的数字,我们用count记录一下。

      不断遍历1~n,找到第一行有而第二行or第三行没有的数字,最重要的是把第一行的对应数字归零(这样就不会判断到它),然后对应得一列删除。

      设置一个flag,判断每次删除情况,未删则跳出。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e5+10;
     4 int n;
     5 int ct1[N],ct2[N],ct3[N];
     6 int t2[N],t3[N],ans;
     7 int main(){
     8     scanf("%d",&n);
     9     for(int i=1;i<=n;i++){
    10         scanf("%d",&ct1[i]);
    11     }
    12     for(int i=1;i<=n;i++){
    13         scanf("%d",&ct2[i]);
    14         t2[ct2[i]]++;
    15     }
    16     for(int i=1;i<=n;i++){
    17         scanf("%d",&ct3[i]);
    18         t3[ct3[i]]++;
    19     }
    20     bool flag=false;
    21     while(!flag){
    22         flag=true;
    23         for(int i=1;i<=n;i++){
    24             if(ct1[i]&&!(t2[ct1[i]]&&t3[ct1[i]])){
    25                 flag=false;
    26                 ct1[i]=0;
    27                 ans++;
    28                 t2[ct2[i]]--;
    29                 t3[ct3[i]]--;
    30             }
    31         }
    32     }
    33     printf("%d",ans);
    34     return 0;
    35 }

    4.区间

    Description

      Alice收到一些很特别的生日礼物:区间。即使很无聊,Alice还是能想出关于区间的很多游戏,其中一个是,Alice从中选出最长的不同区间的序列,其中满足每个区间必须在礼物中,另序列中每个区间必须包含下一个区间。
      编程计算最长序列的长度。
     

    Input

      输入文件第一行包含一个整数N(1<=N<=100000),表示区间的个数。
      接下来N行,每行两个整数A和B描述一个区间(1<=A<=B<=1000000)。

    Output

      输出满足条件的序列的最大长度。

    这道题用了一点贪心的思想,我们将右端从大到小排序,这样遍历只用考虑左端点即可。

    考虑包含关系,每一个左端点都要比上一个左端点大,所以就是找最长不下降子序列的问题了。

    这里复习一下:

      我们用len表示答案长度,或者说答案区间的长度,遍历数组,每测到一个新的值,就与答案数组的len位置比较,如果大于ans[len],则直接令ans[++len]=a[i],即更新答案长度,但是如果小于,则在答案数组中找到一个比这个数大的第一个数与之替换(因为本来也可以绕过那个数到达这个数,且不会影响答案)(这里使用upper_bound,注意返回的是地址,要减去初地址(如果是数组就减去数组名称)),然后没了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e6+10;
     4 struct line{
     5     int l,r;
     6 }a[N];
     7 int n,f[N];
     8 bool cmp(line t1,line t2){
     9     if(t1.r==t2.r) return t1.l<t2.l;
    10     else return t1.r>t2.r;
    11 }
    12 int main(){
    13     scanf("%d",&n);
    14     for(int i=1;i<=n;i++){
    15         scanf("%d%d",&a[i].l,&a[i].r);
    16     }
    17     sort(a+1,a+n+1,cmp);
    18     f[1]=a[1].l;
    19     int len=1;
    20     for(int i=2;i<=n;i++){
    21         if(a[i].l>=f[len]) f[++len]=a[i].l;
    22         else{
    23             int j=upper_bound(f+1,f+len+1,a[i].l)-f;
    24             f[j]=a[i].l;
    25         }
    26     }
    27     printf("%d\n",len);
    28     return 0;
    29 }

    总结:还是很菜,明天继续。

    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    ubuntu12.04 安装eclipse
    loj 1429(可相交的最小路径覆盖)
    loj 1406(状态压缩)
    mysql数据库表插入单条数据/批量插入数据
    window7安装MongoDB详细步骤
    django中的setting全局变量的导入
    django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE的解决办法(转)
    DjangoDRF序列化组件使用
    python并发编程知识点总结
    协程+IO切换实现并发
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11290892.html
Copyright © 2011-2022 走看看