显然是一个搜索题……但是我的方法好像偏了? 速度是还可以,但是代码长,占用内存多。
用邻接表的方式,来保存 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; }