zoukankan      html  css  js  c++  java
  • $NOIP2004$ 题解报告

    目录

    •$Luogu P1089$ 津津的储蓄计划$( √ )$

    •$Luogu P1090$ 合并果子$( √ )$

    •$Luogu P1091$ 合唱队形$( √ )$

    •$Luogu P1092$ 虫食算$( √ )$


    $Luogu P1089$ 津津的储蓄计划

    题目传送门

     

    $NOIP$提高组中唯一一道入门题$QwQ$

    直接暴力模拟就$ok$了,放下代码就好

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int main(){
     4     int n,m,x=0,a=0,b=0,d=0;
     5     bool c=0;
     6     for(int i=1;i<=12;i++)
     7      {
     8         cin>>n;
     9         m=300+a-n;
    10         if(m>=0) {x+=m/100;a=m%100;}
    11         else{m=0;a=0;c=1;}
    12         b++;
    13         if(c==1&&d==0)
    14           {d=b;c=0;}
    15      }
    16      if(d!=0) cout<<-d;
    17      else cout<<120*x+a;
    18      
    19     return 0;
    20 }
    代码戳这里

    $Luogu P1090$ 合并果子

    题目传送门

    可以直接用$STL$中的$priority_queue$,也可以手写堆

    每次取出堆顶$($小根堆$)$的两个元素,将其和加进答案并重新插入堆

    放下$STL$的代码

     1 #include<bits/stdc++.h>
     2 #define ri register int
     3 #define ll long long
     4 #define rl register ll
     5 #define go(i,a,b) for(ri i=a;i<=b;i++)
     6 #define back(i,a,b) for(ri i=a;i>=b;i--)
     7 #define g() getchar()
     8 #define il inline
     9 #define pf printf
    10 #define mem(a,b) memset(a,b,sizeof(a))
    11 using namespace std;
    12 il int fr(){
    13     ri w=0,q=1;char ch=g();
    14     while(ch<'0'||ch>'9'){if(ch=='-')q=-1;ch=g();}
    15     while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=g();
    16     return w*q;
    17 }
    18 int n,ans;
    19 priority_queue<int>q;
    20 int main(){
    21     //freopen(".in","r",stdin);
    22     //freopen(".out","w",stdout);
    23     n=fr();
    24     go(i,1,n){
    25         ri a=fr();
    26         q.push(-a);
    27     }
    28     while(q.size()>1){
    29         ri x=q.top();q.pop();x=-x;
    30         ri y=q.top();q.pop();y=-y;
    31         ans+=x+y;x+=y;
    32         q.push(-x);
    33     }
    34     if(!ans)ans+=q.top();
    35     pf("%d
    ",ans);
    36     return 0;
    37 }
    STL版

    $Luogu P1092$ 合唱队形

    题目传送门

    设$b[i]$表示正着数到第$i$个人,包括第$i$个人在内最多能留下多少个人,$c[i]$表示倒着数

    最后枚举中间的分界点,使得$b[i]+c[i]$最大,答案为$n-max{b[i]+c[i]}+1$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int a[200],b[200],c[200];
     4 int main(){
     5     int n,i,j,maxx;
     6     cin>>n;
     7     memset(b,0,sizeof(b));
     8     memset(c,0,sizeof(c));
     9     for(i=1;i<=n;i++)
    10       cin>>a[i];
    11     for(i=1;i<=n;i++)
    12      {
    13          b[i]=1;
    14          for(j=1;j<=i-1;j++)
    15            if((a[i]>a[j])&&(b[j]+1>b[i])) b[i]=b[j]+1;
    16      }
    17     for(i=n;i>=1;i--)
    18      {
    19          c[i]=1;
    20          for(j=i+1;j<=n;j++)
    21            if((a[j]<a[i])&&(c[j]+1>c[i])) c[i]=c[j]+1;
    22      }
    23     maxx=0;
    24     for(i=1;i<=n;i++)
    25       if(b[i]+c[i]>maxx) maxx=b[i]+c[i];
    26     cout<<n-maxx+1<<endl;
    27     return 0;
    28 }
    代码戳这里

    $Luogu P1091$ 虫食算

    题目传送门

    从大到小枚举每个字母代表的数字,一边枚举一边判断是否合法,$dfs+$剪枝即可$AC$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,sum[30],wait[30];
     4 char s1[30],s2[30],s3[30];
     5 bool used[30];
     6 void print(){
     7     for(int i=0;i<n;i++){
     8         if(i==0) printf("%d",sum[i]);
     9         else printf(" %d",sum[i]);
    10     }
    11     exit(0);
    12 }
    13 bool cut(){
    14     if(sum[s1[0]-'A']+sum[s2[0]-'A']>=n) return 0;//如果第一位要进位显然不可能
    15     for(int i=n-1;i>=0;i--){
    16         int A=sum[s1[i]-'A'],B=sum[s2[i]-'A'],C=sum[s3[i]-'A'];
    17         if(A==-1||B==-1||C==-1) continue;
    18         if((A+B)%n!=C&&(A+B+1)%n!=C) return 0;
    19 //如果当前这一位加起来的数字不对,那么也要返回
    20     }
    21     return 1;//如果符合条件则返回1
    22 }
    23 bool pd(){//判断是否成立
    24     int x=0;//x记录进位
    25     for(int i=n-1;i>=0;i--){
    26         int A=sum[s1[i]-'A'],B=sum[s2[i]-'A'],C=sum[s3[i]-'A'];
    27         if((A+B+x)%n!=C) return 0;
    28         x=(A+B+x)/n;
    29     }
    30     return 1;
    31 }
    32 void search(int x){//当前匹配到第x个字母的数字
    33     if(!cut()) return;
    34     if(x==n){
    35         if(pd()) print();
    36         return;
    37     }
    38     for(int i=n-1;i>=0;i--){
    39         if(used[i]) continue;//如果这个数字已经和某个字母匹配过就跳过
    40         used[i]=1;
    41         sum[wait[x]]=i;
    42         search(x+1);//继续匹配下一个字母
    43         used[i]=0;
    44         sum[wait[x]]=-1;//回溯
    45     }
    46     return;
    47 }
    48 int num=0;
    49 void get(int x){
    50     if(used[x]==0){
    51         used[x]=1;
    52         wait[num++]=x;//把需要对应数字的字母找出来记录好
    53         return;
    54     }
    55 }
    56 int main(){
    57     freopen("alpha.in","r",stdin);
    58     freopen("alpha.out","w",stdout);
    59     cin>>n;
    60     memset(sum,-1,sizeof(sum));
    61     scanf("%s",s1);
    62     scanf("%s",s2);
    63     scanf("%s",s3);
    64     for(int i=n-1;i>=0;i--){
    65         get(s1[i]-'A');
    66         get(s2[i]-'A');
    67         get(s3[i]-'A');
    68     }
    69     memset(used,0,sizeof(used));//标记清零
    70     search(0);
    71     return 0;
    72 }
    代码戳这里
  • 相关阅读:
    鸽巢原理(The Pigeonhole Principle)(抽屉原理)
    VS2010显示行号
    HDU 2546 饭卡
    组合数学之排列组合(Permutations and Combinations)(四种情况)
    php中的$_SERVER方法初识
    重新认识hasLayout——IE浏览器css bug的一大罪恶根源 转
    javascript实现简单的链式调用
    Javascript 静态类的实现
    Object类相关的属性,方法和操作符
    <转>前端开发中的MCRV模式
  • 原文地址:https://www.cnblogs.com/THWZF/p/11760893.html
Copyright © 2011-2022 走看看