您的位置:首页 > 其它

【HDU 4876多校】ZCC loves cards【搜索】

2014-07-24 20:24 369 查看
题意:给你n个数字,让你选出k个按照一定顺序围成一个环,然后每次可以任取连续的m个(m <= k)数字进行异或,看能构造连续的数列【L,R】求出最大值R。

思路:就按照正常思想来做,对于n个数字。枚举从中选出k个数,然后再对于这个k个数进行全排列,对于每次排列都更新答案。不过这里要进行一个优化,因为数据是随机生成的。所以每次进行全排列时,都需要2^k的复杂度来判断这k个数字不按照顺序任取几个进行异或,得到的连续数列是否比已知的答案更优,不然则不对次k个数字进行全排列。

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

int n, K, L, ca, cnt[120], val[22], tmp[22], ans, num[10], dn[10], S[22];
bool vis[220];
int TF[220] = {0}, F[220] = {0};

void getans() {
int i = L;
for (i;;i++) if (F[i] != ca) break;
if (i > L) ans = ans>(i-1)?ans:(i-1);
}

void ddfs(int d, int v) {
int i, j, qb, k;
if (d == K) {
for (i = 0;i < d;i++) {
qb = 0;
for (j = 0;j < d;j++) {
qb ^= dn[(i+j)%d];
F[qb] = ca;
}
}
getans();
ca++;
}
vis[v] = true;
for (i = 0;i < K;i++) {
if (vis[i]) continue;
dn[d] = num[i];
ddfs(d+1, i);
}
vis[v] = false;
}

void cal() {
int st = 1<<K, i, j, tm = 0, f = 0, tf = 0;
for (i = 0;i < st;i++) {
tm = 0;
for (j = 0;j < K;j++) {
if (i&(1<<j)) tm ^= num[j];
}
if (tm >= L) TF[tm] = ca;
}
for (i = L;;i++) if (TF[i] != ca) break;
ca++;
if (i == L || i-1 <= ans) return;
for (i = 0;i < K;i++) {
dn[0] = num[i];
ddfs(1, i);
}
}

void dfs(int d, int id) {
int i, j, c;
if (S
-S[id]+d < K) return;
if (d == K)
{
c = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < tmp[i]; j++)
num[c++] = val[i];
}
cal();
return;
}
if (id == n) return;
for (j = 0; j <= cnt[val[id]]; j++)
{
tmp[id] = j;
dfs(d+j, id+1);
tmp[id] = 0;
}
}

int main() {
int i, j;
ca = 1;
while (~scanf("%d%d%d", &n, &K, &L)) {
memset(cnt, 0, sizeof(cnt));
S[0] = 0;
for (i = 0;i < n;i++) scanf("%d", &val[i]), cnt[val[i]]++;
sort(val, val+n);
n = unique(val, val+n)-val;
for (i = 0;i < n;i++) S[i+1] = S[i]+cnt[val[i]];
ans = 0;
dfs(0, 0);
printf("%d\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: