• codves 3052 多米诺 && codves 1022 覆盖


    3052 多米诺
     
    时间限制: 1 s
     空间限制: 256000 KB
     题目等级 : 钻石 Diamond
     
    题目描述 Description

    一个矩形可以划分成M*N个小正方形,其中有一些小正方形不能使用。一个多米诺骨牌占用两个相邻的小正方形。试问整个区域内最多可以不重叠地放多少个多米诺骨牌且不占用任何一个被标记为无法使用的小正方形。

    输入描述 Input Description

    第一行有两个用空格隔开的正整数M和N。

        第二行有一个正整数K,表示共有K个小正方形不能使用。输入数据保证K<=M*N。

        以下K行每行有两个用空格隔开的数X和Y,表示第X行的第Y个小正方形不能使用。

    输出描述 Output Description

    输出最多能放多少个多米诺骨牌。

    样例输入 Sample Input

    3 3

    2

    1 1

    2 2

    样例输出 Sample Output

    3

    数据范围及提示 Data Size & Hint

    对于30%的数据,M=1;

        对于50%的数据,M<=2;

        对于70%的数据,M<=3;

        对于100%的数据,M<=50,N<=50。

    #include<cstdio>
    #include<cstring>
    const int N=55;
    int next[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    int map[N][N],f[N*N][N*N];
    int book[N*N];
    int tag[N*N];
    int n,m,k;
    int p,q;
    bool find(int x)
    {
        for(int i=1;i<=q;i++)
        {
            if(f[x][i]&&(!book[i]))
            {
                book[i]=1;
                if(!tag[i]||(find(tag[i])))
                {
                    tag[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        scanf("%d %d %d",&n,&m,&k);
        
        for(int i=1;i<=k;i++)
            scanf("%d %d",&p,&q),map[p][q]=-1;
        p=0,q=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(map[i][j]!=-1)
                {
                    if((i+j)&1) map[i][j]=++p;
                    else map[i][j]=++q;
                }
    //    for(int i=1;i<=n;i++)
    //    {
    //        for(int j=1;j<=m;j++)
    //            printf("%d ",map[i][j]);
    //        printf("
    ");
    //    }
            
                
        int v,u;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(map[i][j]!=-1&&(i+j)&1)
                    for(int k=0;k<4;k++)
                        {
                            v=i+next[k][0],u=j+next[k][1];
                            if(v>=1&&v<=n&&u>=1&&u<=m&&map[v][u]!=-1)
                                f[map[i][j]][map[v][u]]=1;            
                        }
    //    for(int i=1;i<=p;i++)
    //    {
    //        for(int j=1;j<=q;j++)
    //            printf("%d ",f[i][j]);
    //        printf("
    ");
    //    }
        int ans=0;
        for(int i=1;i<=p;i++)
        {
            memset(book,0,sizeof(book));
            if(find(i)) ans++;
        }    
        printf("%d",ans);
        return 0;
    }
    View Code

    解:预处理黑白染色,在连接奇偶间建边;

    find函数要枚举p,q;

    ----------

    1022 覆盖

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 大师 Master
     
     
    题目描述 Description

    有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。

    输入描述 Input Description

    输入文件的第一行是两个整数NM  (1<=NM<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N1<=Y<=M)。

    输出描述 Output Description

    输出所覆盖的最大面积块(1×2面积算一块)。

    样例输入 Sample Input

    4 4

    6

    1 1

    1 4

    2 2

    4 1

    4 2

    4 4

    样例输出 Sample Output

    4

    解:(同上)用邻接矩阵,5000*5000没MLE,666;

    #include<cstdio>
    #include<cstring>
    const int N=101;
    int next[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    int map[N][N],f[(N*N)>>1][(N*N)>>1];
    int book[(N*N)>>1];
    int tag[(N*N)>>1];
    int n,m,k;
    int p,q;
    bool find(int x)
    {
        for(int i=1;i<=q;i++)
        {
            if(f[x][i]&&(!book[i]))
            {
                book[i]=1;
                if(!tag[i]||(find(tag[i])))
                {
                    tag[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        scanf("%d %d %d",&n,&m,&k);
        
        for(int i=1;i<=k;i++)
            scanf("%d %d",&p,&q),map[p][q]=-1;
        p=0,q=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(map[i][j]!=-1)
                {
                    if((i+j)&1) map[i][j]=++p;
                    else map[i][j]=++q;
                }
    //    for(int i=1;i<=n;i++)
    //    {
    //        for(int j=1;j<=m;j++)
    //            printf("%d ",map[i][j]);
    //        printf("
    ");
    //    }
            
                
        int v,u;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(map[i][j]!=-1&&(i+j)&1)
                    for(int k=0;k<4;k++)
                        {
                            v=i+next[k][0],u=j+next[k][1];
                            if(v>=1&&v<=n&&u>=1&&u<=m&&map[v][u]!=-1)
                                f[map[i][j]][map[v][u]]=1;            
                        }
    //    for(int i=1;i<=p;i++)
    //    {
    //        for(int j=1;j<=q;j++)
    //            printf("%d ",f[i][j]);
    //        printf("
    ");
    //    }
        int ans=0;
        for(int i=1;i<=p;i++)
        {
            memset(book,0,sizeof(book));
            if(find(i)) ans++;
        }    
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    [歌词]世界末日
    AJAX是什么?
    [转]Moving Your Access 2002 Database to SQL Server
    .net from身份验证的配置介绍
    ajax
    cmd常用命令
    查看端口解除端口占用
    好久没进来了,今天发一个原创的DatePicker
    真倒霉,前不久分區表錯誤把我數據全部搞沒了
    DataGrid利用DataView过滤,排序
  • 原文地址:https://www.cnblogs.com/12fs/p/7635676.html
Copyright © 2020-2023  润新知