您的位置:首页 > 其它

HDU 5677 ztr loves substring

2016-05-01 14:36 302 查看
Manacher+二维费用多重背包 二进制优化

这题是一眼标算....先计算出每个长度的回文串有几种,然后用二维费用的多重背包判断是否有解。

多重背包做的时候需要二进制优化。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

const int maxn = 300;
int N, p[maxn];
char str[maxn], b[maxn];
int cnt[maxn];
int n, k, L;
bool dp[maxn][maxn];

void init()
{
int i;
for (i = 0; str[i]; i++) b[2 * i + 1] = '#', b[2 * i + 2] = str[i];
N = 2 * i + 1;
b[0] = '$', b
= b[N + 1] = '#';
}

void solve()
{
int i, id, max = 0;
for (i = 1; i <= N; i++)
{
p[i] = i < max ? std::min(max - i, p[2 * id - i]) : 1;
while (b[i + p[i]] == b[i - p[i]]) ++p[i];
if (i + p[i] > max) max = i + p[i], id = i;
cnt[p[i] - 1]++;
}
}
int main()
{
int T; scanf("%d", &T);
while (T--)
{
memset(dp, 0, sizeof dp); dp[0][0] = 1;
memset(cnt, 0, sizeof cnt);
scanf("%d%d%d", &n, &k, &L);
while (n--){ scanf("%s", str); init(); solve(); }
for (int i = 100; i >= 1; i--)
cnt[i] = cnt[i] + cnt[i + 2];
for (int i = 100; i >= 1; i--)
{
if (cnt[i] == 0) continue;
int val = i, num = cnt[i];
int t = 1;
while (num)
{
if (num > t)
{
int tmp_val = val*t;
for (int d = L; d >= 0; d--)
{
for (int f = k; f >= 0; f--)
{
if (dp[d][f] == 0) continue;
if (d + tmp_val <= L&&f + t <= k)
dp[d + tmp_val][f + t] = 1;
}
}
num = num - t;
t = t * 2;
}
else
{
int tmp_val = val*num;
for (int d = L; d >= 0; d--)
{
for (int f = k; f >= 0; f--)
{
if (dp[d][f] == 0) continue;
if (d + tmp_val <= L&&f + num <= k)
dp[d + tmp_val][f + num] = 1;
}
}
num = 0;
}
}
}
if (dp[L][k]) printf("True\n");
else printf("False\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: