题目链接: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 = ;
const LL MOD = 100000000000007ll;
const int N = +;
int a[],b[];
vector<int>val[N];
char str[];
int numa,numb,num,x[],y[];
int gethash(char str[])
{
LL res=str[];
int len=strlen(str);
for(int i=;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,-,sizeof(key));
memset(id,,sizeof(id));
memset(head,-,sizeof(head));
tot=;
}
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 ;
}
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==)return inf;
int low=,high=sz-,mid,ans=-;
while(low<=high)
{
mid=(low+high)>>;
if(val[a][mid]>=x)
{
ans=mid;
high=mid-;
}
else low=mid+;
}
if(ans==-)return abs(x-val[a][sz-]);
else if(ans==)return abs(x-val[a][]);
else return min(abs(x-val[a][ans]),abs(x-val[a][ans-]));
}
int main()
{
int n;
while(scanf("%d",&n),n)
{
scanf("%s",str);
num=;//mp.clear();
HASH.init();
for(int i=;i<*n;i++)scanf("%d",&a[i]),b[i]=str[i]-'a',num+=b[i];
if(num&)
{
puts("-1");continue;
}
for(int i=;i<<<n;i++)val[i].clear();
int sz=;
for(int s=;s<<<n;s++)
{
int tmp=__builtin_popcount(s);
if(tmp>n-tmp)continue;
numa=numb=num=;
for(int j=;j<n;j++)
{
if(s&(<<j))
{
x[numa++]=b[j];
num-=a[j]; }
else
{
y[numb++]=b[j];
num+=a[j];
}
}
if(numa<=numb)
{
int flag=;
for(int k=;k<numa;k++)if(x[k]!=y[k])
{
flag=;break;
}
if(flag)continue;
int siz=;
for(int k=numa;k<numb;k++)str[siz++]=''+y[k];
str[siz]=;
// 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=;i<sz;i++)sort(val[i].begin(),val[i].end());
int ans=inf;
for(int s=;s<<<n;s++)
{
int tmp=__builtin_popcount(s);
if(tmp>n-tmp)continue;
numa=numb=num=;
for(int j=n-;j>=;j--)
{
if(s&(<<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=;
for(int k=;k<numa;k++)if(x[k]!=y[k])
{
flag=;break;
}
if(flag)continue;
int siz=;
for(int k=numb-;k>=numa;k--)str[siz++]=''+y[k];
str[siz]=;
// 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\n",ans);
}
}

hdu 4963(中途相遇法)的更多相关文章

  1. HDU 5936 Difference 【中途相遇法】(2016年中国大学生程序设计竞赛(杭州))

    Difference Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  2. uva 6757 Cup of Cowards(中途相遇法,貌似)

    uva 6757 Cup of CowardsCup of Cowards (CoC) is a role playing game that has 5 different characters (M ...

  3. LA 2965 Jurassic Remains (中途相遇法)

    Jurassic Remains Paleontologists in Siberia have recently found a number of fragments of Jurassic pe ...

  4. 【中途相遇法】【STL】BAPC2014 K Key to Knowledge (Codeforces GYM 100526)

    题目链接: http://codeforces.com/gym/100526 http://acm.hunnu.edu.cn/online/?action=problem&type=show& ...

  5. 高效算法——J 中途相遇法,求和

    ---恢复内容开始--- J - 中途相遇法 Time Limit:9000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Su ...

  6. 【UVALive】2965 Jurassic Remains(中途相遇法)

    题目 传送门:QWQ 分析 太喵了~~~~~ 还有中途相遇法这种东西的. 嗯 以后可以优化一些暴力 详情左转蓝书P58 (但可能我OI生涯中都遇不到正解是这个的题把...... 代码 #include ...

  7. uva1152 - 4 Values whose Sum is 0(枚举,中途相遇法)

    用中途相遇法的思想来解题.分别枚举两边,和直接暴力枚举四个数组比可以降低时间复杂度. 这里用到一个很实用的技巧: 求长度为n的有序数组a中的数k的个数num? num=upper_bound(a,a+ ...

  8. LA 2965 中途相遇法

    题目链接:https://vjudge.net/problem/UVALive-2965 题意: 有很多字符串(24),选出一些字符串,要求这些字符串的字母都是偶数次: 分析: 暴力2^24也很大了, ...

  9. 中途相遇法 解决 超大背包问题 pack

    Description [题目描述] 蛤布斯有n个物品和一个大小为m的背包,每个物品有大小和价值,它希望你帮它求出背包里最多能放下多少价值的物品. [输入数据] 第一行两个整数n,m.接下来n行每行两 ...

  10. 紫书 例题8-3 UVa 1152(中途相遇法)

    这道题要逆向思维, 就是求出答案的一部分, 然后反过去去寻找答案存不存在. 其实很多其他题都用了这道题目的方法, 自己以前都没有发现, 这道题专门考这个方法.这个方法可以没有一直往下求, 可以省去很多 ...

随机推荐

  1. win7系统远程连接其它计算机,并且向远程机传输文件

    首先,打开开始菜单,在程序自带的 “附件“ 中找到 "远程桌面连接"并打开,出现远程桌面对话框: 其次,在对话框左下角点击“选项”,选择“本地资源对话框”,在本地设备和资源下点击“ ...

  2. hdu4722之简单数位dp

    Good Numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tot ...

  3. Linux下基于Erlang的高并发TCP连接压力实验

    1.实验环境: 联想小型机: 操作系统:RedHat Enterprise LinuxServer release6.4(Santiago) 内核版本号:Linux server1 2.6.32-35 ...

  4. ASP.NET Core Authorization

    ASP.NET Core Authorization 本文目录 Asp.net Core 对于授权的改动很友好,非常的灵活,本文以MVC为主,当然如果说webapi或者其他的分布式解决方案授权,也容易 ...

  5. JAVA面试中问及HIBERNATE与 MYBATIS的对比,在这里做一下总结(转)

    hibernate以及mybatis都有过学习,在java面试中也被提及问道过,在项目实践中也应用过,现在对hibernate和mybatis做一下对比,便于大家更好的理解和学习,使自己在做项目中更加 ...

  6. 11.ThinkPHP 3.1.2 连贯操作

    ==================================================== 一.常用连贯操作 1.where 帮助我们设置查询条件 2.order 对结果进行排序 $ar ...

  7. overflow:hidden与position:absolute

    在做一个下拉框的动画效果中遇到了这个bug,记录一下. 在写下拉框的动画的时候,一般我们的做法都是把下拉框的外盒子设为overflow:hidden,然后设下外层盒子高度,之后通过js慢慢的改变高度从 ...

  8. 简单理清一下proto与prototype

    这篇博客主要是为了理清自己的思路. 先上图,所有内容都从这张图来讲. 在js中,所有的东西都是对象,包括是function. prototype这个属性是函数特有的.有两层含义,第一层含义指的是某对象 ...

  9. js正则验证手机号码有效性

    验证130-139,150-159,180-189号码段的手机号码 <script type="text/javascript"> [-]{})|([-]{})|([- ...

  10. 安装m2eclipse

    Help->Eclipse Marketplace- 搜索 maven 安装 Maven Integration for Eclipse