• 【NOIp】NOIp2010


    NOIp2010

    T1 机器翻译

    标签:模拟,STL

    两种做法,同一本质

    1.依题意模拟

    code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,m,x,ans,l,r,a[1005],b[1005];
     4 int main()
     5 {
     6     cin>>m>>n;
     7     l=0;r=0;
     8     for (int i=1;i<=n;i++)
     9     {
    10          scanf("%d",&x);
    11          if (a[x]==0) 
    12          {
    13               ans++;
    14               r++;b[r]=x;a[x]=1;
    15               if (r>m) {l++;a[b[l]]=0;}
    16          }
    17      }
    18      cout<<ans;
    19      return 0;
    20 }
    T1.1

    早期代码

    2.发现题意就是个队列,STL水一波

    code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 namespace gengyf{
     4   inline int read(){
     5     int x=0,f=1;char s=getchar();
     6     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
     7     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
     8     return f*x;
     9   }
    10   int n,m,vis[1005],ans;
    11   queue<int>q;
    12   int main(){
    13     m=read();n=read();
    14     for(int i=1;i<=n;i++){
    15       int x=read();
    16       if(vis[x])continue;
    17       if(q.size()>=m){
    18         int k=q.front();q.pop();
    19         vis[k]=0;
    20       }
    21       q.push(x);vis[x]=1;ans++;
    22     }
    23     printf("%d",ans);
    24     return 0;
    25   }
    26 }
    27 int main(){
    28   gengyf::main();
    29   return 0;
    30 }
    T1.2

    T2 乌龟棋

    标签:dp

    用每种卡片的数量表示状态

    f[i][j][k][l]表示用第一种卡片i张,第二种j张,第三种k张,第四种l张时得到的分数

    用卡片张数就能够算出当前位置

    转移方程为

    f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]+a[pos]) (pos=1+i+2*j+3*k+4*l) pos是当前位置,a[i]表示i位置的分数

    j,k,l同理

    code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 namespace gengyf{
     4     inline int read(){
     5         int x=0,f=1;char s=getchar();
     6         while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
     7         while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
     8         return x*f;
     9     }
    10     int n,m,a[400],tmp[5],st;
    11     int f[50][50][50][50];
    12     int main() {
    13         n=read();m=read();
    14         for(int i=1;i<=n;i++){
    15             a[i]=read();
    16         }
    17         for(int i=1;i<=m;i++){
    18             int x;
    19             x=read();
    20             tmp[x]++;
    21         }
    22         for(int i=0;i<=tmp[1];i++)
    23             for(int j=0;j<=tmp[2];j++)
    24                 for(int k=0;k<=tmp[3];k++)
    25                     for(int l=0;l<=tmp[4];l++){
    26                         st=1+i+j*2+k*3+l*4;
    27                         if(i)f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]+a[st]);
    28                         if(j)f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]+a[st]);
    29                         if(k)f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]+a[st]);
    30                         if(l)f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]+a[st]);
    31                     }
    32         printf("%d",f[tmp[1]][tmp[2]][tmp[3]][tmp[4]]+a[1]);
    33         return 0;
    34     }
    35 }
    36 int main(){
    37     gengyf::main();
    38     return 0;
    39 }
    T2

    T3 关押罪犯

    标签:图论,数据结构

    两种做法

    1.排序后并查集维护犯人之间的怨气值,依据"敌人的敌人是朋友"原则分配监狱

    如果不可避免将两个互为敌人的罪犯分到一个监狱,就输出怨气值

    code

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 struct node {int x,y,z;};
     5 node f[100005];
     6 int n,m,a[20005],b[20005],i;
     7 inline bool cmp(node a,node b)
     8 {
     9     return a.z>b.z;
    10 }
    11 inline int find(int x)
    12 {
    13     if(a[x]==x) return x;
    14     a[x]=find(a[x]);
    15     return a[x];
    16 }
    17 inline void merge(int x,int y)
    18 {
    19     x=find(a[x]);
    20     y=find(a[y]);
    21     a[x]=y;
    22 }
    23 inline bool check(int x,int y)
    24 {
    25     x=find(x);
    26     y=find(y);
    27     if(x==y) return true;
    28     return false;
    29 }
    30 int main()
    31 {
    32     scanf("%d%d",&n,&m);
    33     for(i=1;i<=n;i++) a[i]=i;
    34     for(i=1;i<=m;i++)
    35         scanf("%d%d%d",&f[i].x,&f[i].y,&f[i].z);
    36     sort(f+1,f+m+1,cmp);
    37     for(i=1;i<=m+1;i++)
    38     {
    39         if(check(f[i].x,f[i].y)) {printf("%d",f[i].z);break;}
    40         else
    41         {
    42             if(!b[f[i].x]) b[f[i].x]=f[i].y;
    43                 else {merge(b[f[i].x],f[i].y);}
    44             if(!b[f[i].y]) b[f[i].y]=f[i].x;
    45                 else {merge(b[f[i].y],f[i].x);}
    46         }
    47     }
    48     return 0;
    49 }
    T3.1

    早期代码

    2.二分图

    二分怨气值后黑白染色判断能否形成二分图,如果能就更新答案 

    code(有注释)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 namespace gengyf{
     4   inline int read(){
     5     int x=0,f=1;char s=getchar();
     6     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
     7     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
     8     return f*x;
     9   }
    10   const int maxm=100010;
    11   const int maxn=20010;
    12   int n,m;
    13   struct edge{
    14     int nxt,to,w;
    15   }e[maxm*2];
    16   int head[maxn],cnt,l=0,r,color[maxn];
    17   void add(int from,int to,int w){
    18     e[++cnt].to=to;e[cnt].nxt=head[from];
    19     e[cnt].w=w;head[from]=cnt;
    20   }
    21   bool check(int x){
    22     queue<int>q;
    23     memset(color,0,sizeof(color));
    24     for(int i=1;i<=n;i++){
    25       if(color[i])continue;
    26       q.push(i);color[i]=1;
    27       while(!q.empty()){
    28         int k=q.front();q.pop();
    29         for(int j=head[k];j;j=e[j].nxt){
    30           if(e[j].w>=x){
    31             if(!color[e[j].to]){//没染过色
    32               color[e[j].to]=(color[k]==1?2:1);
    33               q.push(e[j].to);
    34               //涂上相反颜色入队
    35             }
    36             else if(color[e[j].to]==color[k])return 0;
    37             //如果出现矛盾直接返回(不为二分图)
    38           }
    39         }
    40       }
    41     }
    42     return 1;
    43   }
    44   int main(){
    45     n=read();m=read();
    46     for(int i=1;i<=m;i++){
    47       int u,v,w;
    48       u=read();v=read();w=read();
    49       r=max(r,w);
    50       add(u,v,w);add(v,u,w);
    51     }
    52     r++;
    53     while(l+1<r){
    54       int mid=(l+r)>>1;
    55       if(check(mid)){//染色法判断二分图如果可行就缩小范围
    56         r=mid;
    57       }
    58       else l=mid;
    59     }
    60     printf("%d",l);
    61     return 0;
    62   }
    63 }
    64 int main(){
    65   gengyf::main();
    66   return 0;
    67 }
    T3.2

    T4 引水入城

    标签:搜索

    把第一排每个点都dfs一遍,找到这个点能覆盖的底层点,看能不能覆盖完

    如果不能直接返回

    如果能覆盖完,可以发现每一个第一排的点覆盖的都是底层的一段区间,于是问题转化为最小区间覆盖,贪心或dp都可解

    code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 namespace gengyf{
     4     const int inf=1e9+7;
     5     inline int read(){
     6         int x=0,f=1;char s=getchar();
     7         while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
     8         while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
     9         return f*x;
    10     }
    11     int a[550][550],v[550][550],vl[550],f[505];
    12     int block,cnt,ans,n,m;
    13     struct node{
    14         int l,r;
    15     }c[10005];
    16     void dfs(int x,int y,int k){
    17         v[x][y]=1;
    18         if(x==n){
    19             vl[y]=1;
    20             c[k].l=min(c[k].l,y);
    21             c[k].r=max(c[k].r,y);
    22         }
    23         if(a[x][y]>a[x+1][y]&&!v[x+1][y]&&x!=n)dfs(x+1,y,k);
    24         if(a[x][y]>a[x-1][y]&&!v[x-1][y]&&x!=1)dfs(x-1,y,k);
    25         if(a[x][y]>a[x][y-1]&&!v[x][y-1]&&y!=1)dfs(x,y-1,k);
    26         if(a[x][y]>a[x][y+1]&&!v[x][y+1]&&y!=m)dfs(x,y+1,k);
    27     }
    28     int main(){
    29         n=read();m=read();
    30         for(int i=1;i<=n;i++)
    31             for(int j=1;j<=m;j++){
    32                 a[i][j]=read();
    33             }
    34         for(int i=1;i<=m;i++){
    35             c[i].l=f[i]=inf;
    36         }
    37         f[0]=0;
    38         for(int i=1;i<=m;i++){
    39             if(a[1][i-1]<=a[1][i]&&a[1][i+1]<=a[1][i]){
    40                 dfs(1,i,i);
    41             }
    42             memset(v,0,sizeof(v));
    43         }
    44         for(int i=1;i<=m;i++){
    45             if(!vl[i])block++;
    46         }
    47         if(block){
    48             printf("0
    %d",block);
    49             return 0;
    50         }
    51         for(int i=1;i<=m;i++)
    52             for(int j=1;j<=m;j++){
    53                 if(i>=c[j].l&&i<=c[j].r){
    54                     f[i]=min(f[i],f[c[j].l-1]+1);
    55                 }
    56             }
    57         printf("1
    %d",f[m]);
    58         return 0;
    59     }
    60 }
    61 int main(){
    62     gengyf::main();
    63     return 0;
    64 }
    T4

    总结: 思维难度逐渐上升,有点NOIp的样子了,题目的多解也能够带来很大启发

  • 相关阅读:
    后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
    BZOJ 1001 狼抓兔子 (网络流最小割/平面图的对偶图的最短路)
    FFT与多项式、生成函数题目泛做
    BZOJ 2243 SDOI 2011染色
    莫队/分块 题目泛做
    Cogs 12 运输问题2 (有上下界网络流)
    可并堆/左偏树 题目泛做
    TC快速搜索在win10下不可用
    (转)Tomcat调优
    (转)Tomcat文件详解
  • 原文地址:https://www.cnblogs.com/gengyf/p/11508171.html
Copyright © 2020-2023  润新知