题目链接: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. Android应用之基本的组件(一)

    请大家伙多多指教: 邮箱:weimingweicom@sina.com 请关注:ailiandeziwei 总的页面: 注意:按钮间方法的改变需要:     android:onClick=" ...

  2. excel通过转成xml格式模板,下载成excel文件

    源代码: report ztest_down_excel. data: begin of i_file occurs , val() type c, end of i_file. data begin ...

  3. NET 2016

    .NET 2016   阅读目录 初识 .NET 2016 使用 .NET Framework 4.6 编译应用程序 使用 .NET Core CLI 编译应用程序 小结 厚积薄发这个词是高三英语老师 ...

  4. android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 3

           今天在写一个小项目的数据库部分的功能时,出现了一个这样的问题:java.lang.RuntimeException: Failure delivering result ResultIn ...

  5. 内嵌W5100的网络模块WIZ812MJ--数据手册

    1.简介 WIZ812MJ是一款内嵌了W5100(TCP/IP硬件芯片,内置PHY).MAG-JACK(带变压器的RJ45)和其他胶连逻辑的网络模块.它可以当作一个组件使用,而且不需要为W5100和变 ...

  6. &#181;C/OS-II版本升级指南

    IDE:     MDK V4+ MCU:   LPC17xx(Cortex-M3) RTOS: µC/OS-II        升级顺序:V2.52->V2.62->V2.76-> ...

  7. 11586 - Train Tracks

    Problem J: Train Tracks Andy loves his set of wooden trains and railroad tracks. Each day, Daddy has ...

  8. Ubuntu 14.04LTS Gnome GUI初体验及163更新源配制

    Ubuntu 14.04 LTS于前天(2014.4.17)公布, 我今天将我的系统升级到最新, 体验了下最新的UI系统. 我选择了Ubuntu Gnome 的GUI界面.我曾经的系统是12.04lt ...

  9. Cocos2d-x 手游聊天系统需求分析

    手游聊天系统需求分析 转载请注明:IT_xiao小巫 移动开发狂热者群:299402133 策划需求图 參考系统:刀塔传奇 点击这个.然后弹出以下的对话框 游戏类型:卡牌 分析:刀塔传奇聊天系统分为3 ...

  10. androidstudio 优化gradle编译效率

    androidstuido 使用gradle自己主动构建和编译.有时做少量改动编译须要等待时间过长,近期Erik Hellman编写的Boosting the performance for Grad ...