zoukankan      html  css  js  c++  java
  • upcoj 1975 棋盘覆盖二分匹配+2107单调队列+1109

    首先是A题,这题知道用二分做之后自己做了一遍,开始建图没用好思路,然后就想到了建图的方法,主要是二分匹配要注意的点是:2个集合。

    确定两个集合之间的关系,而不要在一个集合上自身匹配。

    然后就无限WA了,样例和自己列的数据都过了,死磕都WA     后来问肖太爷,他建图方法比我简单多了,我是一个一个枚举搜索来区分组的,他就直接找不相邻的直接分组了,囧囧。

    给出自己的挫WA代码吧。好歹思路是对的- -,我已经debug好久了。。。

    1975:

    //最大匹配
    #include<iostream>
    #include<cstring>
    using namespace std;
    int dx[2]={0,-1};
    int dy[2]={1,0};
    int map[3100][3100];
    int g[60][60];
    int b[60][60];
    int tmp[3100];
    int num[60][60];
    int flag[3100];
    int n,m;int lx,ly;
    int DFS(int x)
    {
    
        for(int i=0;i<=ly;i++)
        {
            if(!flag[i]&&map[x][i])
            {
                flag[i]=1;
                if(tmp[i]==-1||DFS(tmp[i]))
                {
                    tmp[i]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        int T,i,k,j,sum,count,x,y;
        cin>>T;
        while(T--)
        {
            cin>>n>>m;
            for(i=0;i<n;i++)
            for(j=0;j<m;j++)
            {
                cin>>g[i][j];
            }
            //建图
            memset(map,0,sizeof(map));
            memset(tmp,-1,sizeof(tmp));
            memset(b,0,sizeof(b));
            memset(num,0,sizeof(num));
            count=1;//第一个标记为1集合
            lx=-1;ly=-1;  //代表1 2 集合的下标
            for(i=0;i<n;i++)
            for(j=0;j<m;j++)
            {
                if(!g[i][j])
                {
                    if(b[i][j]==0)//1为一个集合  -1为一个集合 0为空洞
                    {
                        b[i][j]=count;       //初始化
                        lx++;num[i][j]=lx;   //num  记录i,j坐标的元素在其集合上的下标
    
                    }
                    for(k=0;k<2;k++)
                    {
                        if(i+dx[k]>=0&&i+dx[k]<n&&j+dy[k]>=0&&j+dy[k]<m&&!g[i+dx[k]][j+dy[k]])
                        {
                                if(b[i+dx[k]][j+dy[k]]==0)
                                {
                                    b[i+dx[k]][j+dy[k]]=-b[i][j];  //相邻2点集合必定不同
                                    if(b[i+dx[k]][j+dy[k]]==1){lx++;num[i+dx[k]][j+dy[k]]=lx;}
                                    else {ly++;num[i+dx[k]][j+dy[k]]=ly;}
                                    //将不同集合的连续两点加入图中
                                    x=num[i][j];y=num[i+dx[k]][j+dy[k]];
                                    if(b[i][j]==1)
                                    map[x][y]=1;
                                    else
                                    map[y][x]=1;
                                }
                        }
                    }
                }
            }
            for(i=0;i<=lx;i++)
            {
                cout<<endl;
                for(j=0;j<=ly;j++)
                {
                    cout<<map[i][j]<<' ';
                }
            }
            sum=0;
            for(i=0;i<=lx;i++)
            {
                memset(flag,0,sizeof(flag));
                sum+=DFS(i);
            }
            if(sum%2==1)
            cout<<"甲"<<endl;
            else
            cout<<"乙"<<endl;
            //cout<<sum<<endl;
        }
    }
    


     

    然后是肖的代码:

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    #define N 2100
    int a[60][60],f[N][N],link[N],v[N],ma[N][N],i,j,k,m,n,x,y,z,t,ans,t1,t2;
    bool dfs(int x)
    {
        int i,j;
        for (i=1;i<t1;i++)
        if (!v[i]&&f[x][i])
        {
            v[i]=1;
            if (link[i]==0||dfs(link[i]))
            {
                link[i]=x;return true;
            }
        }
        return false;
    }
    int main()
    {
        scanf("%d",&t);
        while (t--)
        {
            memset(a,0,sizeof(a));
            memset(f,0,sizeof(f));
            memset(link,0,sizeof(link));
            memset(ma,0,sizeof(ma));
            scanf("%d%d",&n,&m);
            for (i=1;i<=n;i++)
             for (j=1;j<=m;j++)
              {
                  scanf("%d",&a[i][j]);
                  a[i][j]=a[i][j]^1;
              }
            t1=1,t2=1;
            for (i=1;i<=n;i++)
             for (j=1;j<=m;j++)
             {
                 if ((i+j)%2==1&&a[i][j])ma[i][j]=t1++;
                 if ((i+j)%2==0&&a[i][j])ma[i][j]=t2++;
             }
            for (i=1;i<=n;i++)
             for (j=1;j<=m;j++)
             if ((i+j)%2==0)
             {
                 if (j>1&&a[i][j-1])f[ma[i][j]][ma[i][j-1]]=1;
                 if (i>1&&a[i-1][j])f[ma[i][j]][ma[i-1][j]]=1;
                 if (i<n&&a[i+1][j])f[ma[i][j]][ma[i+1][j]]=1;
                 if (j<m&&a[i][j+1])f[ma[i][j]][ma[i][j+1]]=1;
             }
            int ans=0;
            for (i=1;i<t2;i++)
            {
                memset(v,0,sizeof(v));
                if (dfs(i))ans++;
            }
            if (ans%2==0)printf("ÒÒ\n");else printf("¼×\n");
        }
    }
    


    后面两题也很水,水题都过不了主要是分析的问题,分析问题太弱了- -

    2107   这题主要是要控制好stack栈顶的进出,一般单调队列都需要注意这个问题,代码很容易理解

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int stack[1000005];
    int a[1000005];
    int c[1000005];
    int main()
    {
        int n,i,top,k,x;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        top=0;
        memset(stack,0,sizeof(stack));
        memset(c,0,sizeof(c));
        for(i=1;i<=n;i++)
        {
            while(top>0)
            {
                if(top>0&&stack[top]>=a[i])top--;
                else break;
            }
            if(top==0)c[i]=-1;
            else c[i]=stack[top];
            top++;
            stack[top]=a[i];
        }
        scanf("%d",&k);
        while(k--)
        {
            scanf("%d",&x);
            printf("%d\n",c[x]);
        }
        return 0;
    }
    


    1109 这题其实找规律就行了,用了点动态规划的思想。好好学DP啊。。。

    #include<iostream>
    #include<cstring>
    using namespace std;
    int dp[2][20];
    int main()
    {
        int n,j,k;
        cin>>n>>k;
        int sum;
        memset(dp,0,sizeof(dp));
        dp[0][1]=1;
        dp[1][1]=k-1;
        for(int i=2;i<=n-1;i++)//代表位置
        {
            dp[1][i]=dp[1][i-1]+dp[0][i-1];
            dp[0][i]=dp[1][i-1];
    
                dp[1][i]*=k-1;
                dp[0][i]*=1;
        }
        sum=dp[0][n-1]+dp[1][n-1];
        cout<<sum*(k-1)<<endl;
        return 0;
    }
    


     

  • 相关阅读:
    iOS开发UI篇—CAlayer简介
    iOS开发UI篇—ios手势识别(双击、捏、旋转、拖动、划动、长按, 上下左右滑动)
    录屏专家
    加载Gif图片方法
    制作酸奶方法
    UITabBar小红点(适配iPad)
    那些著名或非著名的iOS面试题-后编
    iOS学习资源
    实用的Mac软件
    安装iOS企业包流程
  • 原文地址:https://www.cnblogs.com/amourjun/p/5134171.html
Copyright © 2011-2022 走看看