2017 ACM 南宁现场赛 J. Rearrangement(思维)

一路wa着wa着就绿了。。。。
wa了7,8次搞得心累。。。
题意: 给你2n个数字,填入2*n 的一个矩阵,然后让你满足下列2个条件:
1.矩阵的每一行的和 不能够被3整除
2.矩阵的每一列的和 不能被3整除
思路:
首先我们肯定是要对每个数字进行处理的。。
可是怎么处理的 ? 被3整除其实就是%3就可以了。
那接下来就是构造这个矩阵了;
每个数字被3取余后, 会变成0 , 1 ,2 ;
那首先我们肯定是要先对矩阵的列考虑
我们如果不想让一个列的和被3整除
那么他们的之和就不能 == 0 或者 == 3
所以我们只要找 0 1 , 0 2 , 1 1 , 22 这四个组合 就可以构建成这一个矩阵
例如 :
给你 5 个 2 , 5 个 0 , 10 个 1
那么我就可以构建出这种方案 :
0 0 1 1 1 1 2 2 2 2
1 2 1 1 1 1 2 2 2 2
这时候我们会发现上下两行都会被3整除
那么这时,我只要交换一下位置就好 :
1 0 1 1 1 1 2 2 2 2
0 2 1 1 1 1 2 2 2 2
这样子就可以形成了一个完美的方案

#include <cstring>
#include <cstdlib>
#include<bits/stdc++.h>
#include <cstdio>
#include <queue>
#define INF 0x3fffffff
#define RE(x) (x)^1
#define S 1
using namespace std ;
map<int , int > q ;
int arr[500000] ;
int ans[500000] ;
bool solve(int n) ;
int main(){
  int t ;
  cin >> t ;
  while(t--){
    q.clear() ;
    int n ;
    cin >> n ;
    int x ;
    for(int i = 0 ; i < 2 * n ; i++ ){
        scanf("%d",&x) ; x = x % 3 ;
        q[x]++ ;
        arr[i] = x  ;
    }
    sort(arr , arr + 2*n )  ;
    if( solve(n) ) cout << "YES" << endl ;
    else cout << "NO" <<endl ;
  }
}

bool solve(int n){
    if(q[0] > n ) return false ; // 有超过一行的0的时候,结果肯定是no
    if(q[0] == n) return true ;  //0填上一行的时候,下面就可以随便填充了,如果下面一行的和%3 == 0 ,交换位置即可
    if(q[0]<=1&&q[1]&&q[2]) return false ;//0的个数小于等于1时,会有 11 或者是 12 相邻
    if(q[0]>=2&&q[1]&&q[2])  //特判一下
            {
                if(q[0]==2&&q[1]%2==0&&q[2]%2==0)return false;//如果有2012的个数均为偶数时 , 就会出现 1 2 或者 2 1 的情况(左边为第一行 , 右边为第二行)
                else return true;

}
}

猜你喜欢

转载自blog.csdn.net/qq_42894605/article/details/82192388