题意:给出一个数列(n<=300),Permutation a1, a2, …, an is prettier than permutation b1, b2, …, bn, if and only if there exists an integer k (1 ≤ k ≤ n) where a1 = b1, a2 = b2, …, ak - 1 = bk - 1 and ak < bk all holds。然后给出一张表,告诉你每一次可将哪两个元素可以交换。输出最优排列。
解法:先用floyd求出每个元素经过一定次数的交换可以和哪个元素换位置,然后用贪心求解,保证最左边的数尽量小。
code:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
#define ysk(x) (1<<(x))
typedef long long ll;
//const int INF = 0x3f3f3f3f ;
const int maxn= 300 ;
int n,a[maxn+3];
bool dp[maxn+3][maxn+3];
void floyd()
{
for1(i,n) dp[i][i]=1;
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
dp[j][i]=dp[i][j]= dp[i][j]|| dp[i][k]&&dp[k][j];
}
}
}
}
void greedy()
{
for1(i,n)
{
int k=i;
for(int j=i+1;j<=n;j++) if(a[j]<a[k]&&dp[i][j])
{
k=j;
}
if(k!=i) swap(a[i],a[k]);
}
for1(i,n)
{
printf("%d%c",a[i],i==n?'\n':' ');
}
}
int main()
{
scanf("%d",&n);
for1(i,n) scanf("%d",&a[i]);
char ch;
for1(i,n) for1(j,n)
{
scanf(" %c",&ch);
dp[i][j]= ch=='1'?1:0;
}
floyd();
greedy();
return 0;
}