显然是一个搜索题……但是我的方法好像偏了? 速度是还可以,但是代码长,占用内存多。
用邻接表的方式,来保存 i这个数字,到哪些数字的海明距离不到D的。 用链表的方式存储vis数组, 然后用链表的方式删除,这样穷举剩余可以使用的数字的时候速度会快很多,特别是如何求解的数量的话……
但是别人好像都不是这么做的……好像直接暴力不做任何优化,虽然可能比我的慢,但是如果常数更小的话,会到0ms, 而且使用内存比我小二十倍这样……
我真是太弱了
#include <cstdio>
int N , B, D, maxnum, ans[65];
struct link_table
{
link_table *pre, *next;
int vis;
int t;
link_table()
{
pre = next = this;
vis = 1;
}
}b[256], begin, end;
bool flag = 0;
inline void link_del(int x)
{
--b[x].vis;
if (!b[x].vis)
{
b[x].pre -> next = b[x].next;
b[x].next -> pre = b[x].pre;
}
}
inline void link_add(int x)
{
++b[x].vis;
if (b[x].vis >= 1)
{
b[x].pre -> next = &b[x];
b[x].next -> pre = &b[x];
}
}
struct edge
{
edge *next;
int k;
edge()
{
next = this;
k = -1;
}
edge(int K_, edge *NEXT_)
{
k = K_;
next = NEXT_;
}
edge* rz(){return this;}
}*a[256], *ra[256], Tnull, *null = &Tnull;
inline void edge_ins(edge **R, int A, int B)
{
R[A] = new edge(B, R[A]);
}
void init()
{
int tmp, dis;
scanf("%d%d%d", &N, &B, &D);
maxnum = (1 << B) - 1;
/*建立图,a[i]的链表表示i可以到达的数字*/
for (int i = 0; i <= maxnum; ++ i) a[i] = ra[i]= null;
for (int i = 0; i != maxnum ; ++ i)
for (int j = i + 1; j <= maxnum; ++ j)
{
dis = 0;
tmp = i ^ j;
while (tmp & (-tmp))
{
++ dis;
tmp ^= tmp & (-tmp);
}
if (dis < D) edge_ins(a, i, j), edge_ins(a, j, i); //选了i,就不能选j
}
for (int i = 0; i != maxnum; ++ i)
for (edge *j = a[i]; j != null; j = j -> next) edge_ins(ra, i, j->k); //反向构建边
/*构建所搜链表*/
begin.pre = &begin;
begin.next = &b[0];
b[0].pre = &begin;
for (int i = 0; i != maxnum; ++ i)
{
b[i].t = i;
b[i].next = &b[i + 1];
b[i + 1].pre = &b[i];
}
b[maxnum].next = &end;
b[maxnum].t = maxnum;
end.pre = &b[maxnum];
end.next = &end;
}
void dfs(int k) //合格的数字数量
{
if (flag) return;
if (k > N)
{
flag = 1;
for (int i = 1; i < N; ++ i)
{
if (i % 10 == 0) printf("%d\n",ans[i]);
else printf("%d ",ans[i]);
}
printf("%d\n", ans[N]);
return;
}
/*选择一个数字开始穷举*/
for (link_table *i = begin.next; i != & end; i = i -> next)
{
if (flag) return;
int now = i -> t;
int tmp = 0;
link_del(now);
for (edge *j = a[now]; j != null; j = j -> next) link_del(j -> k);
ans[k] = now;
dfs(k + 1);
for (edge *j = ra[now]; j != null; j = j -> next) link_add(j -> k);
link_add(now);
}
}
int main()
{
init();
dfs(1);
return 0;
}