Following Orders POJ - 1270(全排列 + 字符比较)

题目:

给定 变量列表 和 x < y 形式的变量约束列表,你将要编写一个程序,该程序打印出与约束一致的所有变量排序。
例如,给定约束x < y和x < z,变量x,y,z仅存在两个排序符合约束:xyz 和 xzy (已字符串形式表示)
INPUT
输入有多组测试数据。每组由两行组成:第一行为变量列表,然后下一行为约束列表。约束变量两两配对给出,其中 x y 表示 x < y
所有变量均为单字符小写字母,且变量个数不会超过20。约束至少有一对,并且不会超过50个。符合约束的字符串将至少有一个,且不会超过300个
输入以文件结尾终止
OUTPUT
对于每组输入,应打印符合约束的所有排列。如有多个则按字典序打印,每行一个
每两组输出用空行分隔
Sample Input
a b f g
a b b f
v w x y z
v y x v z v w v
Sample Output
abfg
abgf
agbf
gabf

wxzvy
wzxvy
xwzvy
xzwvy
zwxvy
zxwvy
SOURCE
https://vjudge.net/problem/POJ-1270

思路:

我是用全排列对比约束条件解的,400ms左右,第一次因为用getchar()读入给判超时难受 ,改为fgets才过的,为了处理方便我把字符转换成数字,然后用next_permutation()循环跑全排列

难点在于判断:可以用数组记录约束,如cmp[x][y] = 1 表示 x < y那么在字符串中只需检查字符之间两两是否存在cmp[y][x] == 1如有,则不符合(怎么理解呢,就是比如我们约束cmp[3][4],但是某串中存在了cmp[4][3] == 1,那就不符合条件)期间用vector记录字符串,符合条件打印即可

补充:

定义:从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
公式:全排列数f(n)=n!(定义0!=1)

具体实现:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include<iomanip>
using namespace std;
typedef long long LL;
typedef long double LD;
typedef unsigned long long ULL;
const int maxn = 1e4+10;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
//int dz[] = {0, 0, 0, 0, 1,-1};
//int dx[] = {1,-1, 0, 0, 0, 0};
//int dy[] = {0, 0, 1,-1, 0, 0};
//int dx[] = {1,-1, 0,0};
//int dy[] = {0, 0,-1,1};
//struct P {
//    int z, x, y;
//    P(int z = 0, int x = 0, int y = 0): z(z), x(x), y(y) {}
//};
struct P {
    int x, y;
    P(int x = 0, int y = 0): x(x), y(y) {}
};
//int h, r, c, t;
//int s[55][55][55];
//int d[55][55][55];
//P pre[5][5];
//inline bool in_border (int mz, int mx, int my) {
//    return mx>=0 && mx<r && my>=0 && my<c && mz>=0 && mz<h;
//}
//bool cmp (const void* p1, const void* p2) {
//    return true;
//}
void print(vector<int> v) {
    for(int i = 0; i < v.size(); i++)
        printf("%c", v[i] + 'a');
    printf("\n");
}
int main() {//int T; cin >> T; getchar();
    char s[300];
    int a[25], flag = 0;
    while(fgets(s, 250, stdin)) { //END_OF_FILE return NULL ~ false
        if(flag) printf("\n"); flag = 1;
        int n = 0;
        for(int i = 0; s[i]; i++)
            if(isalpha(s[i])) a[n++] = s[i] - 'a';
        sort(a, a+n); //后面要全排列 所以排序不可少

        fgets(s, 250, stdin);//读入约束条件
        int cmp[30][30]={0}, f = 0;//f标记小的还是大的
        char ct;//存小的
        for(int i = 0; s[i]; i++)
            if(isalpha(s[i])) {
                if(f) {
                    cmp[ct - 'a'][s[i] - 'a'] = 1;
                    f = 0;
                }
                else { ct = s[i]; f = 1;}
            }

        do{
            vector<int> v; f = 1; 
            for(int i = 0; f && i < n; i++) {
                v.push_back(a[i]);
                for(int j = i+1; j < n; j++)
                    if(cmp[ a[j] ][ a[i] ]) { //check 注意顺序哦
                        f = 0; break;
                    }
            }
            if(f) print(v); //符合全部约束就打印吧
        } while(next_permutation(a, a+n)); //动态全排列
    }
    return 0;
}
发布了54 篇原创文章 · 获赞 43 · 访问量 1953

猜你喜欢

转载自blog.csdn.net/Jungle_st/article/details/104669344