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 = ;
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(中途相遇法)的更多相关文章
- HDU 5936 Difference 【中途相遇法】(2016年中国大学生程序设计竞赛(杭州))
Difference Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- uva 6757 Cup of Cowards(中途相遇法,貌似)
uva 6757 Cup of CowardsCup of Cowards (CoC) is a role playing game that has 5 different characters (M ...
- LA 2965 Jurassic Remains (中途相遇法)
Jurassic Remains Paleontologists in Siberia have recently found a number of fragments of Jurassic pe ...
- 【中途相遇法】【STL】BAPC2014 K Key to Knowledge (Codeforces GYM 100526)
题目链接: http://codeforces.com/gym/100526 http://acm.hunnu.edu.cn/online/?action=problem&type=show& ...
- 高效算法——J 中途相遇法,求和
---恢复内容开始--- J - 中途相遇法 Time Limit:9000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Su ...
- 【UVALive】2965 Jurassic Remains(中途相遇法)
题目 传送门:QWQ 分析 太喵了~~~~~ 还有中途相遇法这种东西的. 嗯 以后可以优化一些暴力 详情左转蓝书P58 (但可能我OI生涯中都遇不到正解是这个的题把...... 代码 #include ...
- uva1152 - 4 Values whose Sum is 0(枚举,中途相遇法)
用中途相遇法的思想来解题.分别枚举两边,和直接暴力枚举四个数组比可以降低时间复杂度. 这里用到一个很实用的技巧: 求长度为n的有序数组a中的数k的个数num? num=upper_bound(a,a+ ...
- LA 2965 中途相遇法
题目链接:https://vjudge.net/problem/UVALive-2965 题意: 有很多字符串(24),选出一些字符串,要求这些字符串的字母都是偶数次: 分析: 暴力2^24也很大了, ...
- 中途相遇法 解决 超大背包问题 pack
Description [题目描述] 蛤布斯有n个物品和一个大小为m的背包,每个物品有大小和价值,它希望你帮它求出背包里最多能放下多少价值的物品. [输入数据] 第一行两个整数n,m.接下来n行每行两 ...
- 紫书 例题8-3 UVa 1152(中途相遇法)
这道题要逆向思维, 就是求出答案的一部分, 然后反过去去寻找答案存不存在. 其实很多其他题都用了这道题目的方法, 自己以前都没有发现, 这道题专门考这个方法.这个方法可以没有一直往下求, 可以省去很多 ...
随机推荐
- Android应用之基本的组件(一)
请大家伙多多指教: 邮箱:weimingweicom@sina.com 请关注:ailiandeziwei 总的页面: 注意:按钮间方法的改变需要: android:onClick=" ...
- excel通过转成xml格式模板,下载成excel文件
源代码: report ztest_down_excel. data: begin of i_file occurs , val() type c, end of i_file. data begin ...
- NET 2016
.NET 2016 阅读目录 初识 .NET 2016 使用 .NET Framework 4.6 编译应用程序 使用 .NET Core CLI 编译应用程序 小结 厚积薄发这个词是高三英语老师 ...
- android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 3
今天在写一个小项目的数据库部分的功能时,出现了一个这样的问题:java.lang.RuntimeException: Failure delivering result ResultIn ...
- 内嵌W5100的网络模块WIZ812MJ--数据手册
1.简介 WIZ812MJ是一款内嵌了W5100(TCP/IP硬件芯片,内置PHY).MAG-JACK(带变压器的RJ45)和其他胶连逻辑的网络模块.它可以当作一个组件使用,而且不需要为W5100和变 ...
- µC/OS-II版本升级指南
IDE: MDK V4+ MCU: LPC17xx(Cortex-M3) RTOS: µC/OS-II 升级顺序:V2.52->V2.62->V2.76-> ...
- 11586 - Train Tracks
Problem J: Train Tracks Andy loves his set of wooden trains and railroad tracks. Each day, Daddy has ...
- Ubuntu 14.04LTS Gnome GUI初体验及163更新源配制
Ubuntu 14.04 LTS于前天(2014.4.17)公布, 我今天将我的系统升级到最新, 体验了下最新的UI系统. 我选择了Ubuntu Gnome 的GUI界面.我曾经的系统是12.04lt ...
- Cocos2d-x 手游聊天系统需求分析
手游聊天系统需求分析 转载请注明:IT_xiao小巫 移动开发狂热者群:299402133 策划需求图 參考系统:刀塔传奇 点击这个.然后弹出以下的对话框 游戏类型:卡牌 分析:刀塔传奇聊天系统分为3 ...
- androidstudio 优化gradle编译效率
androidstuido 使用gradle自己主动构建和编译.有时做少量改动编译须要等待时间过长,近期Erik Hellman编写的Boosting the performance for Grad ...