CodeForces 500B New Year Permutation (Floyd判断通路是否存在)(贪心)

题目链接:http://codeforces.com/problemset/problem/500/B

B. New Year Permutation
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
User ainta has a permutation p1, p2, …, pn. As the New Year is coming, he wants to make his permutation as pretty as possible.

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.

As known, permutation p is so sensitive that it could be only modified by swapping two distinct elements. But swapping two elements is harder than you think. Given an n × n binary matrix A, user ainta can swap the values of pi and pj (1 ≤ i, j ≤ n, i ≠ j) if and only if Ai, j = 1.

Given the permutation p and the matrix A, user ainta wants to know the prettiest permutation that he can obtain.

Input
The first line contains an integer n (1 ≤ n ≤ 300) — the size of the permutation p.

The second line contains n space-separated integers p1, p2, …, pn — the permutation p that user ainta has. Each integer between 1 and n occurs exactly once in the given permutation.

Next n lines describe the matrix A. The i-th line contains n characters ‘0’ or ‘1’ and describes the i-th row of A. The j-th character of the i-th line Ai, j is the element on the intersection of the i-th row and the j-th column of A. It is guaranteed that, for all integers i, j where 1 ≤ i < j ≤ n, Ai, j = Aj, i holds. Also, for all integers i where 1 ≤ i ≤ n, Ai, i = 0 holds.

Output
In the first and only line, print n space-separated integers, describing the prettiest permutation that can be obtained.


题目大意与解析:判断可能达到的最完美的排序。其中给出的数字为1到n中的一个排序,给出一个矩阵s[i][j],只有当s[i][j]的值是1的时候第i个数和第j个数可以做交换。用Floyd判断出每个数字最终可能到达的位置。并试图将1到n按照完美顺序放入ans数组中,即将最小的数字尽可能的往前放。

知识点:Floyd算法 http://developer.51cto.com/art/201403/433874.htm


AC代码如下:

#include <iostream>
#pragma comment(linker, "/STACK:1024000000,1024000000") 
#include <stdio.h>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <string>
#include <string.h>
#include <sstream>
#include <cctype>
#include <climits>
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <vector>
#include <iterator>
#include <algorithm>
#include <stack>
#include <functional>
//cout << "OK" << endl;
#define _clr(x,y) memset(x,y,sizeof(x))
#define _inf(x) memset(x,0x3f,sizeof(x))
#define pb push_back
#define mp make_pair
#define FORD(i,a,b) for (int i=(a); i<=(b); i++)
#define FORP(i,a,b) for (int i=(a); i>=(b); i--)
#define REP(i,n) for (int i=0; i<(n); i++)
using namespace std;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const double EULER = 0.577215664901532860;
const double PI = 3.1415926535897932384626;
const double E = 2.71828182845904523536028;
typedef long long LL;
LL pow_mod(LL a,LL n,LL m)
{
    if(n == 0) return 1;
    LL x = pow_mod(a,n>>1,m);
    LL ans = x*x%m;
    if(n&1) ans = ans*a%m;
    return ans;
}
int gcd(int a,int b){return b == 0 ? a : gcd(b,a%b);}


int arr[310],pos[310],visited[310],ans[310];
char s[310][310]; 
int main(){
    int n;
    while(cin >> n){
        FORD(i,1,n){
            scanf("%d",&arr[i]);
            pos[arr[i]] = i;
        }
        //读入数据存放在arr中,并在pos中记录i数值出现的位置

        //读入矩阵,将对角线上的(自己可以和自己交换)的值初始化为1 
        FORD(i,1,n){
            scanf("%s",s[i] + 1);
            s[i][i] = '1';
        }

        //Floyd算法 i为中转的位置,判断从j位置到k位置通过i位置中转是否可能 
        FORD(i,1,n){
            FORD(j,1,n){
                FORD(k,1,n){
                    if(s[j][i] == '1' && s[k][i] == '1'){
                        s[j][k] = '1';
                    }
                }
            }
        }
        _clr(visited,0);

        //在ans数组中的第一个位置,从数值1开始,尽可能将最小的值放在ans的前面 
        for(int i = 1; i <= n; i++){
            //选定当前位置i
            for(int j = 1; j <= n; j++){
                //从1开始判断,j值是否已经用过,如果没有,那是否可能从数字j所在的位置换到当前位置i 
                if(!visited[j] && s[i][pos[j]] == '1'){
                    ans[i] = j;
                    visited[j] = 1;
                    pos[j] = i;
                    pos[arr[i]] = pos[j];
                    break;
                }
            }
        }


        FORD(i,1,n){
            printf("%d ",ans[i]);
        }
        cout << endl; 
    }
    return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值