• CDOJ 1281 暴兵的卿学姐 构造题


    暴兵的卿学姐

    题目连接:

    http://acm.uestc.edu.cn/#/problem/show/1281

    Description

    沈宝宝又和卿学姐开始玩SC2了!

    自从沈宝宝学会新的阵型后,就把卿学姐干的不要不要的,每次都把卿学姐按在地上摩擦。

    卿学姐是我们的学姐啊,不能就这样认怂啊。

    然后卿学姐就开始研究新的阵型(虽然没有什么卵用,咸鱼终究是咸鱼

    这个阵型必须是正方形,必须包含卿学姐所有的兵种(1到n),每个学姐的每种兵也都必须排成正方形。

    比如当n=8的时候,一个可行的解是像下面那种矩阵

    1 1 1 3 3

    1 1 1 3 3

    1 1 1 2 4

    5 5 7 6 6

    5 5 8 6 6

    我们可以认为1代表枪兵,2代表运输机,3代表坦克,4代表光头,5代表雷神,6代表味精,7代表SCV,8代表战列舰。

    卿学姐的每种兵都排成了正方形,并且整个组成了一个正方形。

    按照CodeForces的说法,卿学姐有可能没带电脑,或者不擅长数学,或者在忙别的事情,总之这个问题交到了你的手上。

    只要你教会了卿学姐这个阵型,那么卿学姐就会化身暴兵狂魔,一雪前耻!

    你需要构造一个可行的解,或者判断无解。由于星际2有人口限制,所以最后的矩阵的边长不能超过1000。

    Input

    输入一个整数1<=n<=200000

    Output

    输出一行字符串,如果是能够构造出来,那么输出"Possible",否则输出"Impossible"

    如果是可以构造的,输出一个整数K,表示矩阵的边长

    接下来K行K列,输出这个矩阵

    如果有多解,输出任意解就好~

    Sample Input

    8

    Sample Output

    Possible
    5
    1 1 1 3 3
    1 1 1 3 3
    1 1 1 2 4
    5 5 7 6 6
    5 5 8 6 6

    Hint

    题意

    题解:

    题意:你需要构造一个m*m的正方形,使得里面恰好有n个正方形。m需要<=1000,n<=200000。

    题解:
    这道题怎么做呢?
    首先我们假设没有m<=1000这个条件。
    那么显然除了2的所有偶数n,我们都可以由1+(n-1)组成。
    比如 6:
    1 1 2
    1 1 3
    4 5 6
    比如8:
    1 1 1 2
    1 1 1 3
    1 1 1 4
    5 6 7 8
    比如10
    1 1 1 1 2
    1 1 1 1 3
    1 1 1 1 4
    1 1 1 1 5
    6 7 8 9 10

    然后我们又可以发现一个特质,我们组成一个正方形之后,我们只要再加三个和这个一模一样的正方形就好了,所有2n+3都能组成了~。

    然后除了2,3,5以外的所有都能构造了~

    然后这道题就完了。

    但是,现在有一个条件,就是m需要小于等于1000,数据范围极限是200000。

    我们可以简单思考一下,1000*1000 = 1000000,数据极限范围是200000。

    那么你构造的每个正方形的平均边长小于sqrt(5)就能解决这道题啦。

    在这里我推荐陈鑫的做法:

    这个大正方形内,只需要有边长为2和边长为3的正方形。

    那么假设我有num2个边长为2的正方形,num3个边长为3的正方形,而剩下的全都是边长为1的正方形。

    那么边长为1的正方形的数量为m*m-num2*4-num3*9。

    显然m*m-​num2*4-num3*9==n-num2-num3就好了。

    化简m*m - num2*3-num3*8 = n。

    这个方程,肯定num2越多越好。

    然后贪心的去摆这些正方形就好了,然后就结束了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1050;
    int g[maxn][maxn];
    int cnt=1;
    int main()
    {
        int n;
        scanf("%d",&n);
        if(n==2||n==5||n==3)return puts("Impossible"),0;
        int m = sqrt(n);
        if(m*m==n)
        {
            printf("Possible
    %d
    ",m);
            for(int i=1;i<=m;i++,cout<<endl)
                for(int j=1;j<=m;j++)
                    printf("%d ",cnt++);
            return 0;
        }
        m--;
        while(m++)
        {
            int t = m*m-n;
            int num2 = t/3;
            int num3 = 0;
            if(t%3==0)num3=0;
            else if(t%3==1)num3=2,num2-=5;
            else num3=1,num2-=2;
            if(num2<0)continue;
            if(m*m-num2*3-num3*8!=n)continue;
            memset(g,0,sizeof(g));
            cnt=1;
            for(int i=1;i<=m-2&&num3>0;i++)
            {
                for(int j=1;j<=m-2&&num3>0;j++)
                {
                    int flag = 0;
                    for(int i1=0;i1<3;i1++)
                        for(int j1=0;j1<3;j1++)
                            if(g[i+i1][j+j1])flag=1;
                    if(flag)continue;
                    for(int i1=0;i1<3;i1++)
                        for(int j1=0;j1<3;j1++)
                            g[i+i1][j+j1]=cnt;
                    cnt++;
                    num3--;
                }
            }
    
            for(int i=1;i<=m-1&&num2>0;i++)
            {
                for(int j=1;j<=m-1&&num2>0;j++)
                {
                    int flag = 0;
                    for(int i1=0;i1<2;i1++)
                        for(int j1=0;j1<2;j1++)
                            if(g[i+i1][j+j1])flag=1;
                    if(flag)continue;
                    for(int i1=0;i1<2;i1++)
                        for(int j1=0;j1<2;j1++)
                            g[i+i1][j+j1]=cnt;
                    cnt++;
                    num2--;
                }
            }
    
            for(int i=1;i<=m;i++)
                for(int j=1;j<=m;j++)
                    if(g[i][j]==0)g[i][j]=cnt++;
            if(cnt==n+1)
            {
                printf("Possible
    %d
    ",m);
                for(int i=1;i<=m;i++,cout<<endl)
                    for(int j=1;j<=m;j++)
                        printf("%d ",g[i][j]);
                return 0;
            }
        }
    }
  • 相关阅读:
    OOAD-2 UML建模、类、接口、类图的详细介绍
    OOAD-1 GOF中的23种设计模式的分类和功能
    java核心技术第四章疑问点
    数据结构中的遇到的一些小知识整理
    springboot中一次坑爹的打包体验
    mybatis中@param的使用与否
    mybatis 防止sql注入
    java窗口
    java异常处理
    第三次上级作业
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5265071.html
Copyright © 2020-2023  润新知