• 0x29 总结与练习


    搜索真的菜。。困扰了很久,上个星期天没休息好导致整个礼拜没有精神。。

    大概完成得七七八八了吧。真是深切的体会到暴力出奇迹的疯狂啊。

    3、虫食算 从末位开始枚举判断,通过加数可以推出和的字母代表的数。那么加一个剪枝,就是通过当前所知字母对应值判断是否合法。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    int n,cnt,a[30],c[30];bool bk,v[30];
    char ss[3][30];
    bool check(int k)
    {
        for(int i=k-1;i>=1;i--)
        {
            if(a[ss[0][i]-'A'+1]!=-1&&a[ss[1][i]-'A'+1]!=-1)
            {
                int d=a[ss[0][i]-'A'+1]+a[ss[1][i]-'A'+1];
                if(a[ss[2][i]-'A'+1]!=-1)
                {
                    int dd=a[ss[2][i]-'A'+1];
                    if(dd==d%n||dd==(d+1)%n)continue;
                    return false;
                }
            }
        }
        return true;
    }
    void dfs(int k,int w)
    {
        if(bk==true)return ;
        if(cnt==n||(k==0&&c[k]==0))
        {
            bk=true;
            for(int i=1;i<n;i++)printf("%d ",a[i]);
            printf("%d
    ",a[n]);
            return ;
        }
        if(w==2)
        {
            int x=ss[w][k]-'A'+1;
            int d=a[ss[0][k]-'A'+1]+a[ss[1][k]-'A'+1]+c[k];
            
            if(a[x]==-1)
            {
                if(v[d%n]==true)return ;
                
                a[x]=d%n;c[k-1]=d/n;v[d%n]=true;cnt++;
                if(check(k))dfs(k-1,0);
                a[x]=-1;c[k-1]=0;v[d%n]=false;cnt--;
            }
            else if(a[x]==d%n)
            {
                c[k-1]=d/n;
                dfs(k-1,0);
                c[k-1]=0;
            }
        }
        else
        {
            int x=ss[w][k]-'A'+1;
            if(a[x]==-1)
            {
                for(int i=0;i<n;i++)
                {
                    if(v[i]==false)
                    {
                        a[x]=i;v[i]=true;cnt++;
                        if(check(k))dfs(k,w+1);
                        a[x]=-1;v[i]=false;cnt--;
                    }
                }
            }
            else dfs(k,w+1);
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=0;i<3;i++)scanf("%s",ss[i]+1);
        memset(a,-1,sizeof(a));
        memset(c,0,sizeof(c));
        memset(v,false,sizeof(v));
        bk=false;cnt=0;dfs(n,0);
        return 0;
    }
    虫食算

    4、Mayan游戏 直接枚举移动方案并模拟状态的转移,hash判重就OK了。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<map>
    using namespace std;
    
    int n,cnt,len[10],a[10][10];bool bk;
    struct ansnode{int x,y,z;}as[10];
    
    bool del[10][10];
    void change(int x,int y,int z)
    {
        if(len[x+z]>=y)swap(a[x+z][y],a[x][y]);
        else 
        {
            a[x+z][++len[x+z]]=a[x][y];
            for(int i=y;i<=len[x];i++)swap(a[x][i],a[x][i+1]);
            a[x][len[x]]=0;len[x]--;
        }
        memset(del,false,sizeof(del));
        bool qwq=true;
        while(qwq)
        {
            qwq=false;
            for(int i=1;i<=5;i++)
                for(int j=1;j<=len[i];j++)
                {
                    if(i<=3)
                    {
                        if(a[i][j]==a[i+1][j]&&a[i+1][j]==a[i+2][j])
                        {
                            del[i][j]=true, del[i+1][j]=true, del[i+2][j]=true;
                            qwq=true;
                        }
                    }
                    if(len[i]-j>=2)
                    {
                        if(a[i][j]==a[i][j+1]&&a[i][j+1]==a[i][j+2])
                        {
                            del[i][j]=true, del[i][j+1]=true, del[i][j+2]=true;
                            qwq=true;
                        }
                    }
                }
            for(int i=1;i<=5;i++)
            {
                int tp=0;
                for(int j=1;j<=len[i];j++)
                    if(del[i][j]==false)a[i][++tp]=a[i][j];
                    else cnt--;
                for(int j=tp+1;j<=len[i];j++)a[i][j]=0;
                len[i]=tp;
            }
            memset(del,false,sizeof(del));
        }
    }
    map<int,bool>mp;
    bool myhash(int k)
    {
        int d=k;
        for(int i=1;i<=5;i++)
        {
            for(int j=1;j<=len[i];j++)d=d*11+a[i][j];
            d=d*11;
        }
        if(mp[d]==true)return true;
        else {mp[d]=true;return false;}
    }
    void dfs(int k)
    {
        if(bk==true)return ;
        if(cnt==0&&k==n+1)
        {
            for(int i=1;i<=n;i++)printf("%d %d %d
    ",as[i].x-1,as[i].y-1,as[i].z);
            bk=true;return ;
        }
        if(cnt==0||k==n+1)return ;
        
        int tlen[10],t[10][10],tcnt;
        tcnt=cnt;
        memcpy(tlen,len,sizeof(tlen));
        memcpy(t,a,sizeof(t));
        for(int i=1;i<=5;i++)
        {
            for(int j=1;j<=len[i];j++)
            {
                if(i!=5)
                {
                    change(i,j,1);
                    as[k].x=i, as[k].y=j, as[k].z=1;
                    if(!myhash(k))
                        dfs(k+1);
                    as[k].x=0, as[k].y=0, as[k].z=0;
                    
                    cnt=tcnt;
                    memcpy(len,tlen,sizeof(len));
                    memcpy(a,t,sizeof(a));
                }
                if(i!=1)
                {
                    change(i,j,-1);
                    as[k].x=i, as[k].y=j, as[k].z=-1;
                    if(!myhash(k))
                        dfs(k+1);
                    as[k].x=0, as[k].y=0, as[k].z=0;
                    
                    cnt=tcnt;
                    memcpy(len,tlen,sizeof(len));
                    memcpy(a,t,sizeof(a));
                }
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        memset(len,0,sizeof(len));
        for(int i=1;i<=5;i++)
        {
            while(scanf("%d",&a[i][++len[i]])!=EOF){if(a[i][len[i]]==0)break;}
            len[i]--;cnt+=len[i];
        }
        bk=false;dfs(1);
        if(bk==false)printf("-1
    ");
        return 0;
    }
    Mayan游戏

    5、poj1167 (题意真星星的难理解)现在也学乖了啊,对于这种分组的题要么就是填满一组又一组要么就是一个个加,这里的话是用一个个加的(因为我一开始写的一组又一组TLE啦:)),可以暴力把所有分组方案求出,从多到少填,其中要判断因为前面选了导致现在不合法。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    int n,ans,ti[110];
    struct line{int st,jg,c;}l[4100];int len;
    bool cmp(line l1,line l2){return l1.c>l2.c;}
    
    bool check(int t,int jg)
    {
        while(t<60)
        {
            if(ti[t]==0)return false;
            t+=jg;
        }
        return true;
    }
    void dfs(int k,int sum,int last)
    {
        if(sum==0){ans=min(ans,k);return ;}
        for(int i=last;i<=len;i++)
        {
            if(k+sum/l[i].c>=ans)break;
            if(check(l[i].st,l[i].jg))
            {
                for(int t=l[i].st;t<60;t+=l[i].jg)ti[t]--;
                dfs(k+1,sum-l[i].c,i);
                for(int t=l[i].st;t<60;t+=l[i].jg)ti[t]++;
            }
        }
    }
    int main()
    {
        int x;
        while(scanf("%d",&n)!=EOF)
        {
            memset(ti,0,sizeof(ti));
            for(int i=1;i<=n;i++)
                scanf("%d",&x),ti[x]++;
            len=0;
            for(int st=0;st<30;st++)
                for(int jg=st+1;st+jg<60;jg++)
                    if(check(st,jg))
                    {
                        len++;
                        l[len].st=st;
                        l[len].jg=jg;
                        l[len].c=(59-st)/jg+1;
                    }
            sort(l+1,l+len+1,cmp);
                    
            ans=17;
            dfs(0,n,1);
            printf("%d
    ",ans);
        }
        return 0;
    }
    poj1167

    6、poj3700 这里还是一个个填,有四种情况,开一个新的上升/下降区间,or加入一个以前的上升/下降区间,单论上升,假如可以加入以前的上升区间,根据贪心的思想肯定选比自己小而且最大的那个更新,更加关键的是无需尝试新开一个,这也是贪心等效性的思想。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    int n,ans,c[110],slen[2],s[2][110];
    bool dfs(int k)
    {
        if(slen[0]+slen[1]>=ans+1)return false;
        if(k==n+1)return true;
        
        int id,t;
        id=-1;
        for(int i=1;i<=slen[0];i++)
        {
            if(s[0][i]<c[k])
                if(id==-1||s[0][i]>s[0][id])id=i;
        }
        if(id!=-1)
        {
            t=s[0][id];s[0][id]=c[k];
            if(dfs(k+1))return true;
            s[0][id]=t;
        }
        else
        {
            s[0][++slen[0]]=c[k];
            if(dfs(k+1))return true;
            s[0][slen[0]--]=0;
        }
        
        id=-1;
        for(int i=1;i<=slen[1];i++)
        {
            if(s[1][i]>c[k])
                if(id==-1||s[1][i]<s[1][id])id=i;
        }
        if(id!=-1)
        {
            t=s[1][id];s[1][id]=c[k];
            if(dfs(k+1))return true;
            s[1][id]=t;
        }
        else
        {
            s[1][++slen[1]]=c[k];
            if(dfs(k+1))return true;
            s[1][slen[1]--]=0;
        }
        return false;
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0)break;
            for(int i=1;i<=n;i++)scanf("%d",&c[i]);
            slen[0]=slen[1]=0;
            memset(s,0,sizeof(s));
            for(ans=1;;ans++)
            {
                if(dfs(1))break;
            }
            printf("%d
    ",ans);
        }
        
        return 0;
    }
    poj3700

    7、8、放到练习是侮辱智商??

    9、子串变换 这题跑的挺快啊0ms,我还以为我写的这么又丑又慢会被卡,强行双向bfs,用KMP找子串相等,直接暴力转移状态,然后hash一下判重就差不多了。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    char sc[2][30],ss[2][10][30];
    struct node
    {
        char sl[30];LL d;
    }list[2][110000];char sp[30],su[30];
    map<LL,int>d[2];
    
    int p[30];
    int KMP(int w,int k,int be)
    {
        p[1]=0;int j=0,len=strlen(ss[w][k]+1);
        for(int i=2;i<=len;i++)
        {
            while(j>0&&ss[w][k][i]!=ss[w][k][j+1])j=p[j];
            if(ss[w][k][i]==ss[w][k][j+1])j++;
            p[i]=j;
        }
        j=0;int splen=strlen(sp+1);
        for(int i=1;i<=splen;i++)
        {
            while(j>0&&sp[i]!=ss[w][k][j+1])j=p[j];
            if(sp[i]==ss[w][k][j+1])j++;
            if(j==len&&i-len+1>be)return i-len+1;
        }
        return -1;
    }
    
    map<LL,bool>mp[2];
    int myhash()
    {
        int sulen=strlen(su+1);LL d=0;
        for(int i=1;i<=sulen;i++)d=d*93LL+(LL(su[i]));
        return d;
    }
    
    int main()
    {
        scanf("%s",sc[0]+1);scanf("%s",sc[1]+1);
        int n=0;
        while(scanf("%s",ss[0][++n]+1)!=EOF){scanf("%s",ss[1][n]+1);}
        n--;
        
        int head[2],tail[2];
        
        head[0]=1;tail[0]=2;
        memcpy(list[0][1].sl,sc[0],sizeof(list[0][1].sl));
        memcpy(su,sc[0],sizeof(su));
        list[0][1].d=myhash();mp[0][list[0][1].d]=true;
        d[0][list[0][1].d]=0;
        memset(su,0,sizeof(su));
        
        head[1]=1;tail[1]=2;
        memcpy(list[1][1].sl,sc[1],sizeof(list[1][1].sl));
        memcpy(su,sc[1],sizeof(su));
        list[1][1].d=myhash();mp[1][list[1][1].d]=true;
        d[1][list[1][1].d]=0;
        memset(su,0,sizeof(su));
        
        //--------------init----------------------
        
        while(head[0]<tail[0]&&head[1]<tail[1])
        {
            memcpy(sp,list[0][head[0]].sl,sizeof(sp));int splen=strlen(sp+1);
            LL spd=list[0][head[0]].d;
            if(mp[0][spd]&mp[1][spd]){printf("%d
    ",d[0][spd]+d[1][spd]);return 0;}
            for(int i=1;i<=n&&d[0][spd]<=6;i++)
            {
                int be=KMP(0,i,0);
                while(be!=-1)
                {
                    int len0=strlen(ss[0][i]+1),len1=strlen(ss[1][i]+1);
                    if(splen-len0+len1>25)break;
                    int sulen=0;
                    for(int j=1;j<be;j++)su[++sulen]=sp[j];
                    for(int j=1;j<=len1;j++)su[++sulen]=ss[1][i][j];
                    for(int j=be+len0;j<=splen;j++)su[++sulen]=sp[j];
                    
                    LL sud=myhash();
                    if(!mp[0][sud])
                    {
                        mp[0][sud]=true;d[0][sud]=d[0][spd]+1;
                        memcpy(list[0][tail[0]].sl,su,sizeof(list[0][tail[0]].sl));
                        list[0][tail[0]].d=sud;
                        tail[0]++;
                    }
                    memset(su,0,sizeof(su));
                    
                    be=KMP(0,i,be);
                }
            }
            head[0]++;
            
            
            memcpy(sp,list[1][head[1]].sl,sizeof(sp));splen=strlen(sp+1);
            spd=list[1][head[1]].d;
            if(mp[0][spd]&mp[1][spd]){printf("%d
    ",d[0][spd]+d[1][spd]);return 0;}
            for(int i=1;i<=n&&d[1][spd]<=6;i++)
            {
                int be=KMP(1,i,0);
                while(be!=-1)
                {
                    int len0=strlen(ss[0][i]+1),len1=strlen(ss[1][i]+1);
                    if(splen-len1+len0>25)break;
                    int sulen=0;
                    for(int j=1;j<be;j++)su[++sulen]=sp[j];
                    for(int j=1;j<=len0;j++)su[++sulen]=ss[0][i][j];
                    for(int j=be+len1;j<=splen;j++)su[++sulen]=sp[j];
                    
                    LL sud=myhash();
                    if(!mp[1][sud])
                    {
                        mp[1][sud]=true;d[1][sud]=d[1][spd]+1;
                        memcpy(list[1][tail[1]].sl,su,sizeof(list[1][tail[1]].sl));
                        list[1][tail[1]].d=sud;
                        tail[1]++;
                    }
                    memset(su,0,sizeof(su));
                    
                    be=KMP(1,i,be);
                }
            }
            head[1]++;
        }
        printf("NO ANSWER!
    ");
        return 0;
    }
    子串变换

    10、poj2044 二进制表示状态,记录四个角落多久没降雨,判重即可。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int Bin[30];
    const int dx[9]={0,-2,-1,0,0,1,2,0,0};
    const int dy[9]={0,0,0,-2,-1,0,0,1,2};
    
    int n,u[410];
    bool v[370][9][7][7][7][7];
    int point(int x,int y){return (x-1)*4+y;}
    bool check(int k,int x,int y)
    {
        int zt=0;
        zt^=Bin[point(x,y)];
        zt^=Bin[point(x+1,y)];
        zt^=Bin[point(x,y+1)];
        zt^=Bin[point(x+1,y+1)];
        return (0<x)&&(x<=3)&&(0<y)&&(y<=3)&&(!(zt&u[k]));
    }
    int dfs(int k,int x,int y,int rain[4])
    {
        if(k==n+1)return 1;
        if(v[k][point(x,y)][rain[0]][rain[1]][rain[2]][rain[3]])return 0;
        v[k][point(x,y)][rain[0]][rain[1]][rain[2]][rain[3]]=true;
        for(int i=0;i<=8;i++)
        {
            int tx=x+dx[i],ty=y+dy[i];
            int train[4];memcpy(train,rain,sizeof(train));
            for(int j=0;j<=3;j++)train[j]++;
            if(tx==1&&ty==1)train[0]=0;
            if(tx==3&&ty==1)train[1]=0;
            if(tx==1&&ty==3)train[2]=0;
            if(tx==3&&ty==3)train[3]=0;
            if(check(k,tx,ty)&&train[0]<=6&&train[1]<=6&&train[2]<=6&&train[3]<=6)
            {
                if(dfs(k+1,tx,ty,train))return 1;
            }
            if(k==1)break;
        }
        return 0;
    }
    
    int main()
    {
        Bin[1]=1;for(int i=2;i<=20;i++)Bin[i]=Bin[i-1]*2;
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0)break;
            
            for(int i=1;i<=n;i++)
            {
                u[i]=0;int x;
                for(int j=1;j<=16;j++)
                {
                    scanf("%d",&x);
                    if(x==1)u[i]^=Bin[j];
                }
            }
            memset(v,false,sizeof(v));
            int rain[4];memset(rain,0,sizeof(rain));
            printf("%d
    ",dfs(1,2,2,rain));
        }
        return 0;
    }
    poj2044

    11、留坑

    12、poj1945 这题真的是很奇淫了,较小数不能超过100?gc控到50都没问题

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct node
    {
        int x,y,c;
    }list[1100000];int head,tail;
    bool mp[110][410000];
    void insert(int x,int y,int c)
    {
        if(x>y)swap(x,y);
        if(y>400000||x>100||x<0||mp[x][y])return ;
        mp[x][y]=true;
        
        list[tail].x=x,list[tail].y=y,list[tail].c=c;
        tail++;if(tail==1050000)tail=1;
    }
    
    int main()
    {
        int k;
        scanf("%d",&k);
        head=1,tail=2;
        list[head].x=0,list[head].y=1,list[head].c=0;
        mp[0][1]=true;
        while(head!=tail)
        {
            int x=list[head].x,y=list[head].y,c=list[head].c;
            if(x== k||y==k){printf("%d
    ",c);break;}
            insert(x,x+y,c+1), insert(y,x+y,c+1);
            insert(y-x,y,c+1), insert(y-x,x,c+1);
            insert(x*2,y,c+1), insert(x,y*2,c+1);
            insert(x,x*2,c+1), insert(y,y*2,c+1);
            head++;if(head==1050000)head=1;
        }
        return 0;
    }
    poj1945

    13、poj4007 迭代加深,暴力dfs+bfs找被覆盖的点,当时我满脑子的都是神之折纸的个游戏啊,怎么IDA*,我玩的时候看到步数比颜色少就重来,但是这个故意卡好像。。结果gc%了一发就是这么搞?真是。。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int dx[4]={-1,0,1,0};
    const int dy[4]={0,-1,0,1};
    
    int n,cnt,a[10][10];
    
    int xx[110],yy[110];bool v[10][10];
    bool check(int x,int y,int c){return 0<x&&x<=n&&0<y&&y<=n&&a[x][y]==c;}
    int bfs(int c)
    {
        int head=1,tail=2,cg=0;xx[1]=1,yy[1]=1;
        memset(v,false,sizeof(v));v[1][1]=true;
        while(head<tail)
        {
            int x=xx[head],y=yy[head];
            for(int i=0;i<=3;i++)
            {
                int tx=x+dx[i],ty=y+dy[i];
                if((check(tx,ty,c)||a[tx][ty]==-1)&&v[tx][ty]==false)
                {
                    if(a[tx][ty]!=-1)cg++;
                    v[tx][ty]=true;a[tx][ty]=-1;
                    xx[tail]=tx;yy[tail]=ty;
                    tail++;
                }
            }
            head++;
        }
        return cg;
    }
    bool bb[10];
    int count()
    {
        memset(bb,false,sizeof(bb));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(a[i][j]!=-1)bb[a[i][j]]=true;
        int c=0;
        for(int i=0;i<=5;i++)
            if(bb[i]==true)c++;
        return c;
    }
    int ans;
    bool dfs(int k)
    {
        if(k+count()>ans)return false;
        if(cnt==0)return true;
        
        int t[10][10];
        for(int c=0;c<=5;c++)
        {
            memcpy(t,a,sizeof(t));
            int d=bfs(c);
            if(d>0)
            {
                cnt-=d;
                if(dfs(k+1))return true;
                cnt+=d;
            }
            memcpy(a,t,sizeof(a));
        }
        return false;
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0)break;
            cnt=n*n;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    scanf("%d",&a[i][j]);
            int c=a[1][1];
            cnt--;a[1][1]=-1;
            cnt-=bfs(c);
            if(cnt==0)printf("0
    ");
            else
            {
                for(ans=1;;ans++)
                {
                    if(dfs(0))break;    
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    poj4007

    14、bzoj1085: [SCOI2005]骑士精神

  • 相关阅读:
    python -基础-强大的列表推导式
    python-基础-字符串拼接
    tkinter学习-- 控件一、Label、Button
    python -re模块
    Apache POI XWPF 爬坑指南之二特定位置插入表格、段落、图片
    mybatis报错:Invalid bound statement (not found):
    bootstrap中input输入框后面添加图标
    bootstrap悬浮显示内容
    layui中使用laydate
    与SQL相关解释表关联(left join ... on ... and ...)
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9309892.html
Copyright © 2020-2023  润新知