zoukankan      html  css  js  c++  java
  • hdu 4963(中途相遇法)

    题目链接:Dividing a String

    题意:给定一个2*n(n<=20)的字符串及每个位置的字符包含的权重,求将该字符串分成两个子序列S1、T1,要求S1=T1且abs(weight1-weight2)尽可能地小。

    分析:将字符串分成前半段和后半段来处理,对于前半段字符串从左往右枚举每个字符属于子序列S1还是T1,属于S1的子序列设为A,属于T1的子序列设为B,设A的长度不大于B,那么仅当A是B的前缀时,才有可能使S1=T1,对于后半段从右往左枚举,要求B不大于A且B为A的前缀,那么设他们多出来的那部分为C和C‘,则C和C’顺序互逆时S1=T1。因此map存下字符串C和倒过来的C'(即C),排序处理一下即可。

    处理字符串C时,引用STL的map最好时14258ms,而且同一份代码还T了,后来自己写一个hashmap,10842ms妥妥AC了。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    #include <map>
    #define LL long long
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int SEED = 171;
    const LL MOD = 100000000000007ll;
    const int N = 1500000+7;
    int a[50],b[50];
    vector<int>val[N];
    char str[50];
    int numa,numb,num,x[25],y[25];
    int gethash(char str[])
    {
        LL res=str[0];
        int len=strlen(str);
        for(int i=1;i<len;i++)
        {
            res=(res*SEED+str[i]+MOD)%MOD;
        }
        return res%N;
    }
    struct HASHMAP
    {
        int head[N],next[N],id[N],key[N];
        int tot;
        void init()
        {
            memset(key,-1,sizeof(key));
            memset(id,0,sizeof(id));
            memset(head,-1,sizeof(head));
            tot=0;
        }
        int find(char str[])
        {
            int u=gethash(str);
            for(int i=head[u];~i;i=head[i])
            {
                if(key[i]==u)return id[i];
            }
            return 0;
        }
        void insert(char str[],int x)
        {
            int u=gethash(str);
            key[tot]=u;id[tot]=x;next[tot]=head[u];head[u]=tot++;
        }
    }HASH;
    int solve(int a,int x)
    {
        int sz=val[a].size();
        if(sz==0)return inf;
        int low=0,high=sz-1,mid,ans=-1;
        while(low<=high)
        {
            mid=(low+high)>>1;
            if(val[a][mid]>=x)
            {
                ans=mid;
                high=mid-1;
            }
            else low=mid+1;
        }
        if(ans==-1)return abs(x-val[a][sz-1]);
        else if(ans==0)return abs(x-val[a][0]);
        else return min(abs(x-val[a][ans]),abs(x-val[a][ans-1]));
    }
    int main()
    {
        int n;
        while(scanf("%d",&n),n)
        {
            scanf("%s",str);
            num=0;//mp.clear();
            HASH.init();
            for(int i=0;i<2*n;i++)scanf("%d",&a[i]),b[i]=str[i]-'a',num+=b[i];
            if(num&1)
            {
                puts("-1");continue;
            }
            for(int i=0;i<1<<n;i++)val[i].clear();
            int sz=1;
            for(int s=0;s<1<<n;s++)
            {
                int tmp=__builtin_popcount(s);
                if(tmp>n-tmp)continue;
                numa=numb=num=0;
                for(int j=0;j<n;j++)
                {
                    if(s&(1<<j))
                    {
                        x[numa++]=b[j];
                        num-=a[j];
    
                    }
                    else
                    {
                        y[numb++]=b[j];
                        num+=a[j];
                    }
                }
                if(numa<=numb)
                {
                    int flag=0;
                    for(int k=0;k<numa;k++)if(x[k]!=y[k])
                    {
                        flag=1;break;
                    }
                    if(flag)continue;
                    int siz=0;
                    for(int k=numa;k<numb;k++)str[siz++]='0'+y[k];
                    str[siz]=0;
             //       if(!mp[str])mp[str]=sz++;
                    int temp=HASH.find(str);
                    if(!temp)
                    {
                        HASH.insert(str,sz);
                        temp=sz++;
                    }
                    int suf=temp;
                    val[suf].push_back(num);
                }
            }
            for(int i=0;i<sz;i++)sort(val[i].begin(),val[i].end());
            int ans=inf;
            for(int s=0;s<1<<n;s++)
            {
                int tmp=__builtin_popcount(s);
                if(tmp>n-tmp)continue;
                numa=numb=num=0;
                for(int j=n-1;j>=0;j--)
                {
                    if(s&(1<<j))
                    {
                        x[numa++]=b[n+j];
                        num-=a[n+j];
    
                    }
                    else
                    {
                        y[numb++]=b[n+j];
                        num+=a[n+j];
                    }
    
                }
                if(numa<=numb)
                {
                    int flag=0;
                    for(int k=0;k<numa;k++)if(x[k]!=y[k])
                    {
                        flag=1;break;
                    }
                    if(flag)continue;
                    int siz=0;
                    for(int k=numb-1;k>=numa;k--)str[siz++]='0'+y[k];
                    str[siz]=0;
                 //   if(!mp[str])continue;
                    int temp=HASH.find(str);
                    if(!temp)continue;
                    int suf=temp;
                    ans=min(solve(suf,num),ans);
                }
            }
            if(ans==inf)puts("-1");
            else printf("%d
    ",ans);
        }
    }
    View Code

     

  • 相关阅读:
    Spark监控官方文档学习笔记
    Maven打包排除某个资源或者目录
    源码中的哲学——通过构建者模式创建SparkSession
    CentOS7启动Tomcat报错:./startup.sh: Permission denied
    Centos7 安装 redis
    centos7 查找jdk 安装路径
    Activemq(centos7)开机自启动服务
    /var/run/redis_6379.pid exists, process is already running or crashed解决方案
    activeMQ 修改端口号
    CentOS7.5 通过wget下载文件到指定目录
  • 原文地址:https://www.cnblogs.com/lienus/p/4466657.html
Copyright © 2011-2022 走看看