• 【2018.10.27】消除游戏 / 绝地求生 / 贪心算法


    题目

    我打比赛打到自闭

    话说这比赛真的有区分度吗,暴力能拿很多分诶


    T1

    随便写

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 inline int read(){
     4     int x=0; bool f=1; char c=getchar();
     5     for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
     6     for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
     7     if(f) return x;
     8     return 0-x;
     9 }
    10 int e[33][33],r[33][33],c[33][33],n,m;
    11 int main(){
    12     freopen("elim.in","r",stdin);
    13     freopen("elim.out","w",stdout);
    14     n=read(),m=read();
    15     int i,j;
    16     for(i=1;i<=n;++i)
    17         for(j=1;j<=m;++j)
    18             e[i][j]=read(),
    19             r[i][j]=(e[i][j]==e[i][j-1]) ? r[i][j-1]+1 : 1,
    20             c[i][j]=(e[i][j]==e[i-1][j]) ? c[i-1][j]+1 : 1;
    21     for(i=1;i<=n;++i)
    22         for(j=1;j<=m;++j){
    23             if(r[i][j]>=3){
    24                 if(r[i][j]==3) e[i][j-2]=e[i][j-1]=e[i][j]=0;
    25                 else e[i][j]=0;
    26             }
    27             if(c[i][j]>=3){
    28                 if(c[i][j]==3) e[i-2][j]=e[i-1][j]=e[i][j]=0;
    29                 else e[i][j]=0;
    30             }
    31         }
    32     for(i=1;i<=n;++i){
    33         for(j=1;j^m;++j) printf("%d ",e[i][j]);
    34         printf("%d
    ",e[i][m]);
    35     }
    36     return 0;
    37 }
    View Code

    T2

    其实就是让你找每个人到安全区(圆)的最短路。

    正着做(求每个人到圆的最短路)时间爆炸,考虑反过来做……

    每次从安全区(圆)中的所有点开始向外 $bfs$,求出图中每个点到圆的最短路。由于相邻两格的距离都是 $1$,最先到达某个点的一条路径一定是最短路。时间复杂度是$O(n^2)$。

    然而我是个傻逼,昨天刚提过的多源最短路今天就忘了……

     1 #include<bits/stdc++.h>
     2 #define rep(i,x,y) for(register int i=(x);i<=(y);i++)
     3 #define dwn(i,x,y) for(register int i=(x);i>=(y);i--)
     4 #define maxn 410
     5 #define maxm 100010
     6 #define maxnd (401*401)
     7 using namespace std;
     8 inline int read()
     9 {
    10     int x=0,f=1;char ch=getchar();
    11     while(!isdigit(ch)&&ch!='-')ch=getchar();
    12     if(ch=='-')f=-1,ch=getchar();
    13     while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    14     return x*f;
    15 }
    16 inline void write(int x)
    17 {
    18     int f=0;char ch[20];
    19     if(!x){putchar('0'),putchar('
    ');return;}
    20     if(x<0)x=-x,putchar('-');
    21     while(x)ch[++f]=x%10+'0',x/=10;
    22     while(f)putchar(ch[f--]);
    23     putchar('
    ');
    24 }
    25 int n,m,e,f,h,rx,ry,r;
    26 int sx[maxm],sy[maxm],dis[maxn][maxn],no[maxn][maxn],lft[maxm],qx[maxnd],qy[maxnd],hd,tl;
    27 int yes(int x,int y)
    28 {
    29     if(x<=n&&x>=1&&y<=n&&y>=1)return 1;
    30     return 0;
    31 }
    32 int inr(int x,int y)
    33 {
    34     if((x-rx)*(x-rx)+(y-ry)*(y-ry)<=r*r)return 1;
    35     return 0;
    36 }
    37 inline void push(int x,int y){tl++;qx[tl]=x,qy[tl]=y;return;}
    38 int dtx[9]={-1,0,1,0,-1,-1,1,1},dty[9]={0,1,0,-1,-1,1,1,-1};
    39 void getdis()
    40 {
    41     hd=1,tl=0;
    42     rep(i,1,n)
    43         rep(j,1,n)
    44         {
    45             if(inr(i,j))push(i,j),dis[i][j]=0;
    46             else dis[i][j]=maxnd;
    47         }
    48     while(hd<=tl)
    49     {
    50         int ux=qx[hd],uy=qy[hd];hd++;
    51         rep(i,0,3)
    52         {
    53             int nx=ux+dtx[i],ny=uy+dty[i]; 
    54             if(yes(nx,ny)&&dis[nx][ny]==maxnd)
    55             {
    56                 dis[nx][ny]=dis[ux][uy]+1;
    57                 if(!no[nx][ny])push(nx,ny);
    58             }
    59         }
    60         rep(i,4,7)
    61         {
    62             int nx=ux+dtx[i],ny=uy+dty[i];
    63             if(yes(nx,ny)&&dis[nx][ny]==maxnd&&(!no[ux][ny]||!no[nx][uy]))
    64             {
    65                 dis[nx][ny]=dis[ux][uy]+1;
    66                 if(!no[nx][ny])push(nx,ny);
    67             }
    68         }
    69     }
    70 }
    71 int main()
    72 {
    73     freopen("battleground.in","r",stdin);
    74     freopen("battleground.out","w",stdout);
    75     n=read(),m=read(),e=read(),f=read(),h=read();
    76     rep(i,1,m)lft[i]=h;
    77     rep(i,1,e){int x=read()+1,y=read()+1;no[x][y]=1;}
    78     rep(i,1,m)sx[i]=read()+1,sy[i]=read()+1;
    79     while(f--)
    80     {
    81         rx=read()+1,ry=read()+1,r=read();
    82         getdis();
    83         rep(i,1,m)lft[i]-=dis[sx[i]][sy[i]];
    84         rep(i,1,m)sx[i]=read()+1,sy[i]=read()+1;
    85     }
    86     rep(i,1,m)write(max(lft[i],0));
    87     return 0;
    88 }
    View Code

    T3

    两种做法。

    一种是优先队列(set / 可删堆)维护。

    一个优先队列记录所有度数为 $1$ 的点的度数和编号。归约用。

    为什么不记录度数为 $0$ 的点?因为根据贪心策略,度数为 $0$ 的点一定只有一开始存在,然后最开始做归约就把它们删完了。剩下的所有点只要度数降到 $1$ 就会被删掉,所以不会再有点的度数变成 $0$ 了。

    另一个优先队列记录所有度数大于等于 $2$ 的点,存三个关键字,依次是:点的度数(大到小),相邻节点中度为 $2$ 的点的个数(大到小),点的编号(大到小)。贪心删点用。

    然后很明显了——题目看起来是说了一堆贪心操作,实际上它们就是一个关键字优先级排序,于是成了堆裸题。

    贪心删点时,由于只有删点操作,所以所有点的度数是只减不加的,因此可以直接往堆中插入一个新的减过度数的点,它一定比原来没减度数的点先到达堆顶。所以只接受原图每个点在堆中第一次到达堆顶的信息就可以了。

    暴力减去与删除点连接的所有未删除点的度数即可。

    复杂度分析(最难考点)每个点只有在 当做堆顶 和 度为 $1$ 的时候会执行两次“把周围一圈点的度 $-1$ ”,对于无向图,所有点的度的和 = 边数$*2$ (每条边都让两端点的度数+1),整张图总共最多也就减这么多次度数。所以复杂度是对的。

    不过由于我思想僵化,又没做出来。

    没有这种做法的 $std$ ……先凑乎吧。

    另一种是权值线段树,其实跟堆差不多。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define N 100010
     5 #define mid ((l+r)>>1)
     6 using namespace std;
     7 struct segt
     8 {
     9     int d[N<<2],a[N<<2],b[N<<2],v[N<<2];
    10     int chk1(int x,int y)
    11     {
    12         if (d[x]<0 && d[y]<0) return x;if (d[x]<0) return y;if (d[y]<0) return x;
    13         if (d[x]<=d[y]) return x;if (d[x]>d[y]) return y;
    14     }
    15     int chk2(int x,int y)
    16     {
    17         if (d[x]<0 && d[y]<0) return y;if (d[x]<0) return y;if (d[y]<0) return x;
    18         if (d[x]<d[y]) return y;if (d[x]>d[y]) return x;
    19         if (v[x]<v[y]) return y;if (v[x]>v[y]) return x;return y;
    20     }
    21     void upd(int t,int l,int r,int x,int k1,int k2)
    22     {
    23         while (l<r) if (x<=mid) r=mid,t<<=1;else l=mid+1,t<<=1,t++;
    24         d[t]+=k1,v[t]+=k2;a[t]=b[t]=t;t>>=1;
    25         while (t){a[t]=chk1(a[t<<1],a[t<<1|1]);b[t]=chk2(b[t<<1],b[t<<1|1]);t>>=1;}
    26     }
    27 }sgt;
    28 int n,fir[N],nxt[N*11],to[N*11],vis[N],cnt,du[N],pos[N<<2];
    29 void add(int u,int v){nxt[++cnt]=fir[u];fir[u]=cnt;to[cnt]=v;}
    30 void del(int x)
    31 {
    32     int d=du[x],i,j;du[x]=-1;vis[x]=1;sgt.upd(1,1,n,x,-d-1,0);
    33     for (i=fir[x];i;i=nxt[i]) if (!vis[to[i]])
    34     {
    35         du[to[i]]--;sgt.upd(1,1,n,to[i],-1,-(d==2));if (du[to[i]]==2)
    36         for (j=fir[to[i]];j;j=nxt[j]) if (!vis[to[j]]) sgt.upd(1,1,n,to[j],0,1);
    37         if (du[to[i]]==1)for (j=fir[to[i]];j;j=nxt[j]) if (!vis[to[j]]) sgt.upd(1,1,n,to[j],0,-1);
    38     }
    39 }
    40 int main()
    41 {
    42     freopen("greedy.in","r",stdin);
    43     freopen("greedy.out","w",stdout);
    44     int m,i,j,l,r,t;scanf("%d%d",&n,&m);
    45     for (i=1;i<=m;i++)
    46     {
    47         scanf("%d%d",&l,&r),add(l,r),add(r,l);
    48         sgt.upd(1,1,n,l,1,0);sgt.upd(1,1,n,r,1,0);du[l]++;du[r]++;
    49     }
    50     for (i=1;i<=n;i++) for (j=fir[i];j;j=nxt[j]) if (du[to[j]]==2) sgt.upd(1,1,n,i,0,1);
    51     for (i=1;i<=n;i++){l=t=1;r=n;while (l<r) if (i<=mid) r=mid,t<<=1;else l=mid+1,t<<=1,t++;pos[t]=i;}
    52     for (i=1;i<=n;i++) if (du[i]==0) printf("%d
    ",i),sgt.upd(1,1,n,i,-1,0),du[i]--;
    53     while (1)
    54     {
    55         if (sgt.d[sgt.b[1]]<0) break;t=pos[sgt.a[1]];
    56         if (sgt.d[sgt.a[1]]==0) printf("%d
    ",t),sgt.upd(1,1,n,t,-1,0);
    57         else if (sgt.d[sgt.a[1]]==1)
    58         {
    59             printf("%d
    ",t);
    60             for (i=fir[t];i;i=nxt[i]) if (!vis[to[i]]) del(to[i]);
    61             sgt.upd(1,1,n,t,-1,0);
    62         }
    63         else del(pos[sgt.b[1]]);
    64     }
    65 }
    WJH的线段树
  • 相关阅读:
    Linux Hung Task分析
    Linux内存都去哪了:(1)分析memblock在启动过程中对内存的影响
    《Linux/UNIX系统编程手册》第63章 IO多路复用、信号驱动IO以及epoll
    Linux内核和用户空间通信之netlink
    Linux soft lockup分析
    一款DMA性能优化记录:异步传输和指定实时信号做async IO
    Linux下时钟框架实践---一款芯片的时钟树配置
    使用Kernel NetEm和tc模拟复杂网络环境
    使用Flame Graph进行系统性能分析
    sigsuspend()阻塞:异步信号SIGIO为什么会被截胡?
  • 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/2018_10_27.html
Copyright © 2020-2023  润新知