题目链接: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. 安卓开发06:布局-线性布局 LinearLayout

    LinearLayout把视图组织成一行或一列.子视图能被安排成垂直的或水平的.线性布局是非常常用的一种布局方式. 请看一个布局例子: <LinearLayout xmlns:android=& ...

  2. asp.net 中将汉字转换成拼音

    /// <summary> /// 获取汉字的全拼音 /// </summary> /// <param name="x">传汉字的字符串< ...

  3. jQuery 查询 xml

    加载xml:(注:这个方法在Chrome是用不了的,Chrome是禁止访问本地的xml文件,在ie11里面用不了,ie11的xmlDom文档没有load方法) function loadXML(fil ...

  4. mac 压缩png图片资源 pngcrush命令

    iOS应用是,xcode会对PNG文件进行优化,这样图片预览就无法显示.那么如何查看这些经过优化的文件呢? 优化的动作是由pngcrush 工具完成的,你可以再xcode中找到.pngcrush 支持 ...

  5. Linux下sed,awk,grep,cut,find学习笔记

    awk awk是一种程序语言,对文档资料的处理具有很强的功能.awk擅长从格式化报文或从一个大的文本文件中抽取数据. awk的命令格式为: awk [-F filed-separator] “comm ...

  6. Jenkins快速搭建持续集成

    基于Jenkins快速搭建持续集成环境 Jenkins+tortoisesvn+MSBuild做到持续集成 附Jenkins的使用:http://www.infoq.com/cn/articles/M ...

  7. 深入浅出Hadoop实战开发(HDFS实战图片、MapReduce、HBase实战微博、Hive应用)

    Hadoop是什么,为什么要学习Hadoop?     Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运 ...

  8. UVA它11292 - Dragon of Loowater

    Problem C: The Dragon of Loowater Once upon a time, in the Kingdom of Loowater, a minor nuisance tur ...

  9. 用js制作的几个效果

    一,表格光柱效果(奇偶行不同颜色,鼠标移上变色) <html xmlns="http://www.w3.org/1999/xhtml"><head>< ...

  10. 美化 - DropDownList控件

    地址:http://www.baidufe.com/component/dropdownlist/index.html 效果: 引用JS文件: <link href="Js/DropD ...