题目链接: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. 在Windows上使用CodeLite+MinGW+Clang进行开发

    前几天听说clang 3.4已经release了,然后我又手痒就折腾一下,在这里记录一下折腾的经过. 在以前就试过clang-cl+VC的开发环境,编译代码到是没发现什么大问题,有不少警告而已,不过c ...

  2. spring mvc 和 jstl

    spring ,jstl 在maven配置文件的配置:<dependency><groupId>org.springframework</groupId><a ...

  3. Properties文件及与之相关的System.getProperties操作(转)

    如何使用Java读写系统属性? 读: 简述properties文件的结构和基本用法结构:扩展名为properties的文件,内容为key.value的映射,例如"a=2" 示例用到 ...

  4. perl 使用SUPER类来访问覆盖的方法

    有时候,你希望一个衍生类的方法表现得象基类中的某些方法的封装器 这就是 SUPER 伪类提供便利的地方.它令你能够调用一个覆盖了的基类方法,而不用声明 是哪个类定义了该方 法.(注:不要把这个和第十一 ...

  5. 基于visual Studio2013解决面试题之1307二分查找

     题目

  6. Qt布局管理

    原地址:http://blog.csdn.net/lastsoup/article/details/7028243 设计软件中各个部件的位置排列,有两种方法: 1.设置widget的在父窗体中的坐标和 ...

  7. RAD路线规划2016版

    http://community.embarcadero.com/article/news/16211-embarcadero-rad-studio-2016-product-approach-and ...

  8. java之redis篇(spring-data-redis整合) (转)

    redis的知识:官网 1,利用spring-data-redis整合 项目使用的pom.xml: <project xmlns="http://maven.apache.org/PO ...

  9. arm-linux-gcc下载与安装

    在RHEL 5平台上安装配置arm-linux-gcc  2011-02-23 19:35:40|  分类: 嵌入式开发环境 |  标签: |字号大中小 订阅 . 在linux平台上安装好的基础上,开 ...

  10. .bash_profile与.bashrc和.profile的区分概念

    在Linux系统中配置环境变量相关的文件主要有如下几个,很容易弄混的,这儿简单区分下: /etc/profile:此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行.并从/etc/p ...