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

    目录

    •$Luogu P1514$ 引水入城$( √ )$

    •$Luogu P1525$ 关押罪犯$( √ )$

    •$Luogu P1540$ 机器翻译$( √ )$

    •$Luogu P1071$ 潜伏者$( √ )$


    $Luogu P1514$ 引水入城

    题目传送门

    这题挺简单的,搜索就能过,我用的$dfs$,大概讲一下思路

    设$l[x][y],r[x][y]$记录经过$(x,y)$这一点向沙漠去的水利工程在沙漠中能到达的最左边的城市和最右边的城市。

    初始值$l[n][y]=r[n][y]=y$,从第一行的点开始$dfs$,过程中更新$l,r$的值。

    最后统计答案的时候,如果有沙漠中的城市没有水,就直接计算数量,否则用第一行的点的$l,r$来计算最少要建几个水利工程

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define g() getchar()
     8 #define rg register
     9 #define go(i,a,b) for(rg int i=a;i<=b;i++)
    10 #define back(i,a,b) for(rg int i=a;i>=b;i--)
    11 #define db double
    12 #define ll long long
    13 #define il inline
    14 #define pf printf
    15 #define mem(a,b) memset(a,b,sizeof(a))
    16 using namespace std;
    17 int fr(){
    18     int w=0,q=1;
    19     char ch=g();
    20     while(ch<'0'||ch>'9'){
    21         if(ch=='-') q=-1;
    22         ch=g();
    23     }
    24     while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g();
    25     return w*q;
    26 }
    27 const int N=502;
    28 int n,m,h[N][N],l[N][N],r[N][N];
    29 int cx[4]={0,1,0,-1},cy[4]={1,0,-1,0};
    30 bool vis[N][N];
    31 il void work(rg int x,rg int y){
    32     vis[x][y]=1;
    33     go(i,0,3){
    34         rg int X=x+cx[i],Y=y+cy[i];
    35         if(X<1||X>n||Y<1||Y>m) continue;
    36         if(h[X][Y]>=h[x][y]) continue;
    37         if(!vis[X][Y]) work(X,Y);
    38         l[x][y]=min(l[x][y],l[X][Y]);
    39         r[x][y]=max(r[x][y],r[X][Y]);
    40     }
    41     return;
    42 }
    43 int main(){
    44     //freopen("","r",stdin);
    45     //freopen("","w",stdout);
    46     n=fr();m=fr();
    47     mem(l,0x3f);
    48     go(i,1,m) l[n][i]=r[n][i]=i;
    49     go(i,1,n) go(j,1,m) h[i][j]=fr();
    50     go(i,1,m) if(!vis[1][i]) work(1,i);
    51     rg int as=0;
    52     go(i,1,m) if(!vis[n][i]) as++;
    53     if(as){puts("0");pf("%d
    ",as);return 0;}
    54     int lft=1;
    55     while(lft<=m){
    56         rg int mxr=0;
    57         go(i,1,m) if(l[1][i]<=lft) mxr=max(mxr,r[1][i]);
    58         as++;lft=mxr+1;
    59     }
    60     puts("1");pf("%d
    ",as);
    61     return 0;
    62 }
    代码戳这里

    $Luogu P1525$ 关押罪犯

    题目传送门

    用并查集做就可以了,贪心从大到小扫描每一条边,然后将这条边的两个端点加入不同的集合,如果当前这两个点已经在同一个集合中,则输出这条边的权值。

    要注意一个就是我们记录每条边的两个端点互为敌人,本着敌人的敌人就是朋友的原则,将敌人的敌人与自己加入同一个集合

    注意一下数据会有输出答案为$0$的情况。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define ri register int
     4 #define ll long long
     5 #define rl register ll
     6 #define go(i,a,b) for(ri i=a;i<=b;i++)
     7 #define back(i,a,b) for(ri i=a;i>=b;i--)
     8 #define g() getchar()
     9 #define il inline
    10 #define pf printf
    11 #define mem(a,b) memset(a,b,sizeof(a))
    12 using namespace std;
    13 il int fr(){
    14     ri w=0,q=1;char ch=g();
    15     while(ch<'0'||ch>'9'){if(ch=='-')q=-1;ch=g();}
    16     while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=g();
    17     return w*q;
    18 }
    19 const int N=2e4+2;
    20 const int M=1e5+2;
    21 int n,m,fa[N],ans,emy[N];
    22 struct node{
    23     int u,v,w;
    24 }e[M];
    25 il bool cmp(node x,node y){return x.w>y.w;}
    26 il int find(ri x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    27 il void add(ri x,ri y){ri fx=find(x),fy=find(y);fa[fx]=fy;return;}
    28 int main(){
    29     //freopen(".in","r",stdin);
    30     //freopen(".out","w",stdout);
    31     n=fr();m=fr();
    32     go(i,1,m)e[i]=(node){fr(),fr(),fr()};
    33     sort(e+1,e+1+m,cmp);
    34     go(i,1,n)fa[i]=i;
    35     go(i,1,m){
    36         ri u=e[i].u,v=e[i].v;
    37         ri fu=find(u),fv=find(v);
    38         if(fu==fv){ans=e[i].w;break;}
    39         if(!emy[u])emy[u]=v;
    40         else add(emy[u],v);
    41         if(!emy[v])emy[v]=u;
    42         else add(emy[v],u);
    43     }
    44     pf("%d
    ",ans);
    45     return 0;
    46 }
    代码戳这里

    $Luogu P1540$ 机器翻译

    题目传送门

    大水题,无脑模拟即可

     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 const int M=102;
    19 int n,m,in[M],ans,num;
    20 int main(){
    21     //freopen(".in","r",stdin);
    22     //freopen(".out","w",stdout);
    23     m=fr();n=fr();
    24     go(i,1,n){
    25         ri x=fr();
    26         bool yes=0;
    27         go(j,0,min(num-1,m-1))if(in[j]==x){yes=1;break;}
    28         if(yes)continue;
    29         in[num%m]=x;num++;ans++;
    30     }
    31     pf("%d
    ",ans);
    32     return 0;
    33 }
    代码戳这里

    $Luogu P1071$ 潜伏者

    题目传送门

    因为只有$4$中卡牌,且卡牌的数量范围较小,所以我们直接设$f[a][b][c][d]$表示分别使用了$a,b,c,d$张第$1,2,3,4$种卡牌的最大分数,然后暴力转移即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=352,M=42;
     4 int num[5],s[N];
     5 int f[M][M][M][M];
     6 int n,m;
     7 int main(){
     8     scanf("%d%d",&n,&m);
     9     for(int i=1;i<=n;i++)
    10         scanf("%d",&s[i]);
    11     int color;
    12     for(int i=1;i<=m;i++)
    13         scanf("%d",&color),num[color]++;
    14     f[0][0][0][0]=s[1];
    15     for(int a=0;a<=num[1];a++)
    16         for(int b=0;b<=num[2];b++)
    17             for(int c=0;c<=num[3];c++)
    18                 for(int d=0;d<=num[4];d++){
    19                     int now=1+a+b*2+c*3+d*4;
    20                     if(a!=0)
    21                         f[a][b][c][d]=max(f[a][b][c][d],f[a-1][b][c][d]+s[now]);
    22                     if(b!=0)
    23                         f[a][b][c][d]=max(f[a][b][c][d],f[a][b-1][c][d]+s[now]);
    24                     if(c!=0)
    25                         f[a][b][c][d]=max(f[a][b][c][d],f[a][b][c-1][d]+s[now]);
    26                     if(d!=0)
    27                         f[a][b][c][d]=max(f[a][b][c][d],f[a][b][c][d-1]+s[now]);
    28                 }
    29     printf("%d
    ",f[num[1]][num[2]][num[3]][num[4]]);
    30     return 0;
    31 }
    代码戳这里
  • 相关阅读:
    Reactor系列(四)subscribe订阅
    Reactor系列(三)创建Flux,Mono(续)
    Reactor系列(二)Flux Mono创建
    Reactor系列(一)基本概念
    Stream系列(十五)File方法使用
    Stream系列(十四)parallet方法使用
    OpenCV二值化、归一化操作
    C# 队列
    linux shell脚本程序路径作为变量
    C++中头文件(.h)和源文件(.cpp)都应该写些什么
  • 原文地址:https://www.cnblogs.com/THWZF/p/11745342.html
Copyright © 2011-2022 走看看