Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
Description
It's preseason and the local newspaper wants to publish a preseason ranking of the teams in the local amateur basketball league. The teams are the Ants, the Buckets, the Cats, the Dribblers, and the Elephants. When Scoop McGee, sports editor of the paper, gets the rankings from the selected local experts down at the hardware store, he's dismayed to find that there doesn't appear to be total agreement and so he's wondering what ranking to publish that would most accurately reflect the rankings he got from the experts. He’s found that finding the median ranking from among all possible rankings is one way to go.
The median ranking is computed as follows: Given any two rankings, for instance ACDBE and ABCDE, the distance between the two rankings is defined as the total number of pairs of teams that are given different relative orderings. In our example, the pair B, C is given a different ordering by the two rankings. (The first ranking has C above B while the second ranking has the opposite.) The only other pair that the two rankings disagree on is B, D; thus, the distance between these two rankings is 2. The median ranking of a set of rankings is that ranking whose sum of distances to all the given rankings is minimal. (Note we could have more than one median ranking.) The median ranking may or may not be one of the given rankings.
Suppose there are 4 voters that have given the rankings: ABDCE, BACDE, ABCED and ACBDE. Consider two candidate median rankings ABCDE and CDEAB. The sum of distances from the ranking ABCDE to the four voted rankings is 1 + 1 + 1 + 1 = 4. We'll call this sum the value of the ranking ABCDE. The value of the ranking CDEAB is 7 + 7 + 7 + 5 = 26.
It turns out that ABCDE is in fact the median ranking with a value of 4.
Input
There will be multiple input sets. Input for each set is a positive integer n on a line by itself, followed by n lines (n no more than 100), each containing a permutation of the letters A, B, C, D and E, left-justified with no spaces. The final input set is followed by a line containing a 0, indicating end of input.
Output
Output for each input set should be one line of the form:
ranking is the median ranking with value value.
Of course ranking should be replaced by the correct ranking and value with the correct value. If there is more than one median ranking, you should output the one which comes first alphabetically.
Sample Input
4
ABDCE
BACDE
ABCED
ACBDE
0
Sample Output
ABCDE is the median ranking with value 4.
题目简述:
这道题真的是很长……但是核心内容只有一点:求字符串“ABCDE”的全排列中与给定字符串的差异最小的那个字符串。
重点是 1、如何求“ABCDE”的全排列 2、如何求与所给字符串的差异
算法分析:
递归、回溯、深度优先搜索
数据结构:
结构体
解题思路:
1、求数字{1,2,3,4,5}全排列方法:
#include<cstdio>
#include<iostream>
using namespace std;
int a[1000],v[1000],n;
void print(){
for (int i=1;i<=n;i++) printf("%d ",a[i]); //将每位输出
puts(""); //换行
}
void DFS(int dep){
if (dep==n) print(); //如果搜到一个结果输出
dep++; //查找当前要处理位
for (int i=1;i<=n;i++) { //枚举当前位
if (v[i]) continue; //如果这个数之前被选过就跳过
v[i]=1; //选中当前位
a[dep]=i;//将当前位存入数组
DFS(dep);//搜索下一位
v[i]=0;//取消选中当前位
}
}
int main(){
scanf("%d",&n); //读入
DFS(0); //深搜
}
借鉴上面代码并改动一下就可以了,char类型和int类型其实是对应的 : ‘B’ - 'A' = (int)1;
注:在网上看到很多人写用使用STL<algorithm>的next_permutation函数生成全排列(C++),当然可以啦
#include <algorithm>
bool next_permutation( iterator start, iterator end );
The next_permutation() function attempts to transform the given range of elements [start,end) into the next lexicographically greater permutation of elements. If it succeeds, it returns true, otherwise, it returns false.
3、求两个字符相异程度方法:
例如:ABCDE 和 BACDE
我先给两个字符串里面的字符编号:
1 2 3 4 5
A B C D E
1 2 3 4 5
B A C D E
然后给字符串里的字符按字典序排序,原来的编号不变:
1 2 3 4 5
A B C D E
2 1 3 4 5
A B C D E
之后,我发现,再第一个字符串中编号A<B而在第二个字符串中对应字符的编号A>B,这就表明这是一个差异其余的循环一一对比,总共需要 4+3+2+1=10次比较。
<span style="font-size:14px;">void search() {
for (int k = 1; k <= n; k++)
for (int i = 1; i <= DEEP; i++)
for (int j = i + 1; j <= DEEP; j++)
if ((a[0][i].num < a[0][j].num)
^ (ran[k][i].num < ran[k][j].num))
sum++;
}</span>
代码:
#include <cstdio>
#include <iostream>
#include <stdio.h>
#define DEEP 5
using namespace std;
int v[102], n;
int sum, m;
struct list {
char c;
int num;
};
list ran[101][6]; //储存输入的所有字符串
list a[1][6]; //全排列中的当前排列
list best[1][6]; //最佳结果
//将字符按字典序排序
void sorting(list *p) {
for (int i = 1; i <= DEEP; i++)
for (int j = i + 1; j <= DEEP; j++)
if (p[i].c > p[j].c) {
list hold = p[i];
p[i] = p[j];
p[j] = hold;
}
}
//查找相异
void search() {
for (int k = 1; k <= n; k++)
for (int i = 1; i <= DEEP; i++)
for (int j = i + 1; j <= DEEP; j++)
if ((a[0][i].num < a[0][j].num)
^ (ran[k][i].num < ran[k][j].num))
sum++;
}
//生成全排列
void DFS(int dep) {
if (dep == DEEP) {
list hold[1][6];
for (int i = 1; i <= DEEP; i++) {
hold[0][i] = a[0][i];
}
sorting(a[0]);
sum = 0;
search(); //如果搜到一个结果输出
if (sum < m) {
for (int i = 1; i <= DEEP; i++) {
best[0][i] = hold[0][i];
}
m = sum;
}
//还原现场
for (int i = 1; i <= DEEP; i++) {
a[0][i] = hold[0][i];
}
}
dep++; //查找当前要处理位
for (int i = 1; i <= DEEP; i++) { //枚举当前位
if (v[i])
continue; //如果这个数之前被选过就跳过
v[i] = 1; //选中当前位
a[0][dep].c = i + 'A' - 1; //将当前位存入数组
a[0][dep].num = dep;
DFS(dep); //搜索下一位
v[i] = 0; //取消选中当前位
}
}
int main() {
cin >> n;
m = 10000000;
while (n != 0) {
m = 1000000;
getchar();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= DEEP; j++) {
ran[i][j].c = getchar();
ran[i][j].num = j;
}
getchar();
sorting(ran[i]);
}
DFS(0); //深搜
for (int i = 1; i <= DEEP; i++) {
cout << best[0][i].c;
}
cout << " is the median ranking with value " << m << "." << endl;
cin >> n;
}
return 0;
}