cf B. Brand New Easy Problem

给你一组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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值