给你一组n个字串,然后再给出k组字符串,每组含有mi个。。
然后用n个子串去匹配k组字符串,求最小的逆序对。。。
在匹配k组字符串时出现问题,因为k组字符串中的单词会重复,所以不知怎么去取舍,我是用贪心的方法如果两个单词相等,则比较相邻两个单词,如果前一个单词比后面一个单词大,则删掉,事实这种方法不对,然而我想不到逆向思维,就是利用next_permutation(),求出每个下一个排列中的逆序对,然后再去匹配k组字符串,由于下一个排列中的逆序对是递增的,而且数据小,所以可以很快得出,但是注意一点(刚开始没注意,后来去查数据,唉~~我知道查数据这种方式不太对,但是我感觉自己想不出原因,所以重视忍不住去查数据,这种学习方法已经很多年了,我知道不好,但是不知怎么去改;额),当两个排列的逆序对相等时,要求出的是最小序号,所以每一个排列都要检索。。。。
代码写的很挫~~~感觉还不如大一的人~~~
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,k,a[20];
struct node
{
int s[30];
int mount;
} p[20];
char sr[20][25];
int nixudui()
{
int cnt=0;
for(int i=1; i<=n; i++)
{
for(int j=i+1; j<=n; j++)
{
if(a[i]>a[j])
cnt++;
}
}
return cnt;
}
int main()
{
cin>>n;
char l[30];
for(int i=1; i<=n; i++)
{
cin>>sr[i];
a[i]=i;
}
cin>>k;
for(int i=1; i<=k; i++) //问题个数
{
cin>>p[i].mount;
memset(p[i].s,0,sizeof(p[i].s));
for(int j=1; j<=p[i].mount; j++) //每个问题的单词数
{
cin>>l;
for(int t=1; t<=n; t++)
{
if(!strcmp(l,sr[t]))
{
p[i].s[j]=t;
break;
}
}
}
}
/*输出
for(int i=1;i<=k;i++)
{
for(int j=1;j<=p[i].mount;j++)
cout<<p[i].s[j]<<" ";
}
cout<<endl;*/
int min_p=99999,min_r=1,flag=0;
do
{
int nixu=nixudui();
/*
for(int i=1;i<=n;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;*/
for(int i=1; i<=k; i++)
{
int j=1,t=1;
while(j<=n&&t<=p[i].mount)
{
if(a[j]==p[i].s[t])
{
j++;
t++;
}
else
t++;
}
if(j>n)
{
if(min_p>=nixu)
{
if(min_p==nixu)
min_r=min(min_r,i);
else
{
min_p=nixu;
min_r=i;
}
flag=1;
}
//cout<<min_p<<" "<<min_r<<endl;
}
}
}
while(next_permutation(a+1,a+1+n));
if(!flag)
{
cout<<"Brand new problem!"<<endl;
return 0;
}
cout<<min_r<<endl;
cout<<"[:";
for(int i=1; i<=n*(n-1)/2-min_p+1; i++)
{
cout<<"|";
}
cout<<":]"<<endl;
return 0;
}