zoukankan      html  css  js  c++  java
  • 20190817

    EX1 翻转游戏

    如图,有这样一个4*4的棋盘。每次可以操作一个棋子,这个棋子本身及其周围四个方向的棋子(如果存在)都会被翻转,翻转即由黑变白由白变黑。问最少需要多少步能够使所有棋子都变成同种颜色。

    【输入】

    输如一个4*4的矩阵,w表示白色,b表示黑色,不会出现其他字符。

    【输出】

    输出只有一行,包含所求的最小步数。


    咦,等于4,我就算搜也就2^16=65536

    还想什么,看我一发暴力把他A了

    #include<bits/stdc++.h>
    #define re return
    #define inc(i,l,r) for(int i=l;i<=r;++i)
    using namespace std;
    template<typename T>inline void rd(T&x)
    {
        char c;bool f=0;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
        x=c^48;
        while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
        if(f)x=-x;
    }
    
    int dx[6]={0,0,1,-1,0,0},dy[6]={0,0,0,0,1,-1};
    int n,m,col[10][10],vis[10];
    int ans=17;
    
    inline void dfs(int x,int y,int sum)
    {
        
        if(sum>=ans)re;
        
        vis[0]=0,vis[1]=1;
        inc(i,1,4)inc(j,1,4)vis[col[i][j]]=1;
        if(!vis[0]||(!vis[1]))
        {
            ans=sum;re ;
        }
        
        int flag=1,j;
        inc(i,x,4)
        {
             if(flag)flag=0,j=y+1;
             else j=1;
            for(j;j<=4;++j)
            {
                inc(k,1,5)
                {
                    int nx=i+dx[k],ny=j+dy[k];
                    if(nx<1||ny<1||nx>4||ny>4)continue;
                    col[nx][ny]^=1; 
                }
                dfs(i,j,sum+1);
                inc(k,1,5)
                {
                    int nx=i+dx[k],ny=j+dy[k];
                    if(nx<1||ny<1||nx>4||ny>4)continue;
                    col[nx][ny]^=1; 
                }
            }
            
        }
    }
    int main()
    {
         char ss[10];
        inc(i,1,4)
        {
            scanf("%s",ss+1);
            inc(j,1,4)
            if(ss[j]=='b')col[i][j]=1;
            else col[i][j]=0;
        }
        
        dfs(0,4,0);
        
        if(ans==17)printf("Impossible");
        else printf("%d",ans);
        re 0;
    } 

    咦,怎么只有80

           vis[0]=0,vis[1]=1;

    想想就后怕,我还有80???

    数据有多水,人就有多水

    其实还有一个加强版

    你只需要先确定全改的颜色,然后弄出第一行的状态,状压一下判断翻不翻的问题

    然后全局模拟,最后检验是否符合要求即可

    EX2 岛屿

    从前有一座岛屿,这座岛屿是一个长方形,被划为N*M的方格区域,每个区域都有一个确定的高度。不幸的是海平面开始上涨,在第i年,海平面的高度为t[i]。如果一个区域的高度小于等于海平面高度,则视为被淹没。那些没有被淹没的连通的区域够成一个连通块。现在问第i年,这样的连通块有多少个。 例如:第一年海平面高度为1,有2个连通块。 第二年海平面高度为2,有3个连通块。 图片

    【输入】

    第一行包含两个数N,M。

    接下来是一个N*M的矩阵,第i行第j列表示这个格子的高度h[i][j]

    接下来是一个数T,表示有T天,

    最后一行有T个数,第i个数表示第i天的水位高度。(保证是递增的)

    【输出】

    输出包含一行T个数,第i个数表示第i天的连通块个数。


    连通块?并查集十有八九了。

    cut the relation between a and b

    倒着做就好了

    等一下,这数据范围900万?

    算了算了

    卡一下空间,手动计算

    随便写了写,手动对拍了好久

    嗯,我一定是对的

    80?

    nmggo

    又怎么了

    第一组数据竟然与第十组数据是一样的小数据

    我竟然都错了

    看了看,没维护天数倒叙的合法性

    QAQ

    小细节好多

    #include<bits/stdc++.h>
    #define re return
    #define dec(i,l,r) for(int i=l;i>=r;--i) 
    #define inc(i,l,r) for(int i=l;i<=r;++i)
    using namespace std;
    template<typename T>inline void rd(T&x)
    {
        char c;bool f=0;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
        x=c^48;
        while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
        if(f)x=-x;
    }
    
    const int maxn=3005,maxt=100005;
    int n,m,T,t[maxt],ans[maxt],fa[maxn*maxn];
    
    int dx[5]={0,0,0,1,-1},dy[5]={0,1,-1,0,0};
    struct node{
        int x,val;
        bool operator<(node a)const
        {
            re val>a.val;
        }
    }a[maxn*maxn];
    
    
    inline int find(int x)
    {
        re x==fa[x]?x:fa[x]=find(fa[x]);
    }
    int main()
    {
        rd(n);rd(m);
        inc(i,1,n)
        {
            int v=(i-1)*m;
            inc(j,1,m)
            {
                rd(a[v+j].val);
                a[v+j].x=v+j;
            }
        }
        
        rd(T);
        inc(i,1,T)
        rd(t[i]);
        
        sort(a+1,a+n*m+1);
        int j=T;
        for(int i=1;i<=n*m;++i)
        {
            int f=0;
            while(a[i].val<=t[j])
            {
                --j;
                if(!j)
                {
                    f=1;
                    break;
                 } 
        //就是这个地方 ans[j]
    =ans[j+1]; } if(f)break; ++ans[j]; fa[a[i].x]=a[i].x; int y=a[i].x%m; if(!y)y=m; int x=(a[i].x-y)/m+1; for(int k=1;k<=4;++k) { int nx=(x+dx[k]),ny=y+dy[k]; if(nx<1||ny<1||nx>n||ny>m)continue; nx=(nx-1)*m+ny; if(!fa[nx])continue; int f1=find(a[i].x),f2=find(nx); if(f1!=f2) { --ans[j]; fa[f1]=f2; } } } dec(k,j-1,1)ans[k]=ans[j]; inc(i,1,T) printf("%d ",ans[i]); re 0; }

    EX3 吴神的择偶选择

    【问题描述】

    吴神最常做的一件事,就是在自己的寝室里,仰望着纯白的天花板,寂寞空弹一曲东方花烛夜。

    已经成为神的吴神,有无数的fans,也不乏默默爱慕着他的小正太萝莉,但是这些人吴神都不能成为吴神的另一半(吴神表示有自己的原则,不是因为看不上别人),所以虽然早已到了谈婚论嫁的年龄,吴神还是孑然一身。

    吴神喜欢哲学,但也不排斥异性恋.无聊的时候,看看集训队里谁和谁比较适合,就成了吴神消磨时间的方式。

    在吴神眼里,每个人都有不同的优点,比如高,富,帅,....这些优点被吴神量化成了一个2进制数,每一位表示一种优点是否在这个人身上存在,吴神认为,两个人的优点是不应该有交集的,否则就是浪费!!这对注重效率的吴神是坚决不允许的.比如孜孜的优点可以表示成(1011010) (1011010) ,匀匀的可以表示成(0100100),(1011010)&(0100100)==0(0100100),(1011010)&(0100100)==0 (没有交集),因此在吴神眼里匀匀和孜孜是适合的.吴神是(11111......111111) (11111......111111) ,所以吴神和谁都不合适,因为没有人是没有优点的。

    现在吴神要做的事就是:根据每个人的特征值,在给出的n个人中找到与这个人合适的人,如果有多个,输出特征值最大的那一个,一个人可以被多个人配对.如果没有,输出0。

    【输入】

    第一行为一个n,表示总的人数.第二行是n个数,表示每个人的特征值ai

    【输出】

    输出一行包含N个数,为每个人对应合适的人的最大特征值


    打表,dp,找规律

    个鬼哟!

    先打了个n^2的暴力,又打了个满心以为正确的dfs;

    拍了会,发现dfs,还没我暴力快

    算了,暴力交了一发,竟然水到90pts

    正解

    正难则反

    对于一个数a,如果1111111111……^a=b;

    且 b|c=b;

    我们可以认为a&c=0

    然后你在遍历乱搞一下,差不多就得了

    #include<bits/stdc++.h>
    #define re return
    #define inc(i,l,r) for(int i=l;i<=r;++i)
    using namespace std;
    template<typename T>inline void rd(T&x)
    {
        char c;bool f=0;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
        x=c^48;
        while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
        if(f)x=-x;
    }
    
    int a[1500005],b[1500005];
    //a表示原数,b表示包含b[i]的数
     
    int main()
    {
        freopen("in.txt","r",stdin);
        int n,maxx=0;
        rd(n);
        inc(i,1,n)
        {
            rd(a[i]);
            maxx=max(a[i],maxx);
            b[a[i]]=a[i];
            //存在,初始化 
        }
        
        int cnt=0;
        while((1<<cnt)<=maxx)++cnt;
        
        
        
        inc(i,0,(1<<cnt))
        {
            inc(x,0,cnt)
            if(!((1<<x)&i))
            b[i|(1<<x)]=max(b[i|(1<<x)],b[i]);
            //最大可行解 
        }
        
        inc(i,1,n)
        printf("%d ",b[((1<<cnt)-1)^a[i]]);
        //取反 
        re 0;
    } 
  • 相关阅读:
    转:wap1.1和wap2.0的比较~
    转:alidateRequest=false 在.Net 4.0 中不管用
    ASP.NET页面实时进行GZIP压缩优化
    转:WAP1.0 和 WAP2.0 支持的标签区别
    [转载]利用vs.net快速开发windows服务(c#)
    CSS3选择器
    AD10 多层板设计错误解决
    ASP如何获取客户端真实IP地址
    javascript模拟滚动条实现代码(3)
    最近工作中的小细节
  • 原文地址:https://www.cnblogs.com/lsyyy/p/11368948.html
Copyright © 2011-2022 走看看