CF 266C. Below the Diagonal 思维+递归

题意:n*n的01矩阵,告诉你n-1个1的位置.其余位置都为0.
操作:交换任意两行或者任意两列.
n<=1e3.输出操作序列,使得n-1个1的都在主对线以下.


虽然是交换任意行和任意列,原本在同一列或者同一行上的1,操作后还是在同行同列.

那么n-1个1都在主对角线之下,说明包括主对线线及以上不能有1存在.
设t[j]为第j列上有多少个1. 现在通过列交换 将矩阵变为 t[1]>=t[2]>=...>=t[n]的形式


构造:从最后一个非0列j开始.
若存在a[i][j]=1 (i<=j) 那么找到一个没有换过的行k 并且a[k][j]==0 交换(i,k)这两行,
然后就可以不用再考虑第k行,因为,a[k][j]==1,k>j , 若a[k][p]==1 因为k>j>p 前面也满足.最多交换n-1次.

官方解, 因为只有n-1个1,那么找到一个空列j,把j扔到最后一列, 在找到一个非0行k,把k扔到最后一行.

那么现在可以不考虑第n行和第n列,并且1的个数<=n-2,问题变为(n-1)*(n-1) 放n-2个1的方法.

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef pair<int,int> ii;
const int N=1e3+5;
struct node{
	int col,id;
}p[N];
bool cmp(node a,node b)
{
	return a.col>b.col;
}
int n,a[N][N],now[N];//now[id]现在在第几列. 
vector<ii> res[3];
int mk[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n;
	int x,y;
	rep(i,1,n)	now[i]=i;
	rep(i,1,n-1)
	{
		cin>>x>>y;
		a[x][y]=1;
	}
	rep(j,1,n) 
		rep(i,1,n)
			p[j].col+=a[i][j],p[j].id=j;
	sort(p+1,p+1+n,cmp);
	rep(j,1,n)
	{
		if(j==now[p[j].id])	continue;
		res[2].push_back(ii(j,now[p[j].id]));
		rep(k,1,n)	swap(a[k][j],a[k][now[p[j].id]]);
		rep(k,1,n) 
			if(now[k]==j)
			{
				now[k]=now[p[j].id];
				now[p[j].id]=j;
				break;
			}
	}
	int m=n;
	for(int j=n-1;j>=1;j--)
	{
		for(int i=1;i<=j;i++)
		{
			if(a[i][j]==1)
			{
				for(int k=j+1;k<=n;k++)
					if(!mk[k]&&a[k][j]==0)
					{
						mk[k]=true;
						m=k;
						break;
					}
				res[1].push_back(ii(i,m));		
				//O(n*n)
				for(int k=1;k<=n;k++)
					swap(a[i][k],a[m][k]);
			}
		}
	}
	cout<<res[1].size()+res[2].size()<<'\n';
	for(int i=2;i>=1;i--)
		for(int j=0;j<res[i].size();j++)
			cout<<i<<' '<<res[i][j].first<<' '<<res[i][j].second<<'\n';
	return 0;
}
/* 
1 0 0 1
1 0 0 0
0 0 0 0
0 0 0 0
*/

大佬のcode

//Copyright @ 2012, Chow-Shing Shih, All rights reserved.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <ctime>
#include <utility>
#include <iostream>
#include <cmath>
#define rep(i, n) for (int i = 1; i <= n; ++i)
#define REP(i, n) for (int i = 0; i < n; ++i)
#define INF 0x7fffffff
#define MP(x, y) (make_pair(x, y))
#define pb(x) push_back(x)
#define clr(a, b) memset(a, b, sizeof(a))

using namespace std;

typedef long long llu;

inline int Lowbit(int i){return i & (-i);}
inline void read(int &n)
{
    char c;
    for (c = getchar(); !(c >= '0' && c <= '9'); c = getchar());
    n = c - '0';
    for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) n = n * 10 + c - '0';
}

int tot, N, a[2000][2000], x, y;
vector <pair<int, pair<int, int> > > ans;

int main()
{
    scanf("%d", &N);
    for (int i = 1; i < N; ++i)
    {
        scanf("%d%d", &x, &y);
        a[x][y] = 1;
    }
    while (N > 1)
    {
        int j;
        for (j = 1; j <= N; ++j)
        {
            int tot = 0;
            for (int i = 1; i <= N; ++i)    tot += a[i][j];
            if (tot == 0)break;
        }
        if (j != N && j) ans.push_back(make_pair(2, make_pair(j, N)));
        for (int i = 1; i <= N; ++i)
            a[i][j] = a[i][N], a[i][N] = 0;
        int i;
        for (i = N; i; i--)
        {
            int tot = 0;
            for (int j = 1; j <= N; ++j)    tot += a[i][j];
            if (tot) break;
        }
        if (i != N && i) ans.push_back(make_pair(1, make_pair(i, N)));
        for (int j = 1; j <= N; ++j)
            a[N + 1][j] = a[i][j], a[i][j] = a[N][j], a[N][j] = a[N + 1][j];
        N--;
    }
    printf("%d\n", ans.size());
    for (int i = 0; i < ans.size(); ++i)
        printf("%d %d %d\n", ans[i].first, ans[i].second.first, ans[i].second.second);
 
    return 0;
}


                                                                                            

猜你喜欢

转载自blog.csdn.net/noone0/article/details/80325717