Codeforces 1004D Sonya and Matrix

题目:点击打开链接
题意:给你t个数字,要你组成一个n x m的矩阵,这个矩阵满足这样的条件 ①矩阵里面的元素到“0”这个元素的曼哈顿距离为元素值大小。曼哈顿距离:两个点坐标差的绝对值之和。现在问你的是输出n,m以及元素“0”的坐标(x,y);如果不存在这样的矩阵,输出“-1”。

分析:

由于这个东西具有对称性,每一种解都可以通过翻转将它变化出最多四种解。 
我们仅考虑(x,y)(x,y)在靠近左边界或者上边界的解。 
举个例子,题目中给出了这种情形: 
这里写图片描述 
那么我们可以等价为: 

这里写图片描述 

我们可以假设值为0的点在左上角(x,y),距离点(n,m)最远,可以得出方程n-x+m-y=b(给出的数中的最大值),变形得y=n-x+m-b,n和m很好求,都是t的因子,x为i当ct[i]!=4*i的最小值,因为看图可以得出规律第i(i>0)层数字为i+1的数量为4*i,不满足说明最先出界,也就是值为0的点的x坐标,然后依次枚举根号t以内的因子判断是否满足条件就行了,复杂度为O(sqrt(t)*t),差不多10^9了,codeforces评测机真是快啊。

代码:

#pragma comment(linker, "/STACK:102400000,102400000")///手动扩栈
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<map>
using namespace std;
#define debug test
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define eps 1e-10
#define MOD 1000000007
#define PI acos(-1.0)
const int N = 1e6+10;

ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

int t,x,y,n,m,ct[N],tp[N];

int main() {
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>t;
    int nm,mx=0;
    for(int i=0;i<t;i++) {
        cin>>nm;
        ct[nm]++;
        mx=max(mx,nm);
    }
    for(int i=1;i<=t;i++)
        if(ct[i]!=4*i) {
            x=i;break;
        }
    int flag=1;
    for(int i=1;i*i<=t;i++) {
        if(t%i==0) {
            n=i,m=t/i,y=n-x+m-mx;
            mst(tp,0);
            for(int j=1;j<=n;j++)
                for(int k=1;k<=m;k++)
                    tp[(int)abs(j-x)+(int)abs(k-y)]++;
            int fg=0;
            for(int i=0;i<t;i++) if(ct[i]!=tp[i]) fg=1;
            if(fg==0) {
                cout<<n<<" "<<m<<endl;
                cout<<x<<" "<<y<<endl;
                flag=0;
                break;
            }
        }
    }
    if(flag) cout<<-1<<endl;
    return 0;
}

参考博客:https://blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/80951796

猜你喜欢

转载自blog.csdn.net/tianwei0822/article/details/81056233