Executing... Test 1: TEST OK [0.035 secs, 4000 KB] Test 2: TEST OK [0.032 secs, 4000 KB] Test 3: TEST OK [0.084 secs, 4264 KB] Test 4: TEST OK [0.105 secs, 4264 KB] Test 5: TEST OK [0.132 secs, 4264 KB] Test 6: TEST OK [0.362 secs, 4264 KB] Test 7: TEST OK [0.494 secs, 4264 KB] Test 8: TEST OK [0.672 secs, 4396 KB] Test 9: TEST OK [1.080 secs, 4396 KB] Test 10: TEST OK [1.380 secs, 4396 KB] All tests OK.
认为我程序很慢的就不用看了- - 因为nocow上各种更快的方案。 其实就是搜索顺序不一样,我是按顺序搜索的……各种优化才通关。并且在做的时候,发现,先搜索对角线的确会更快。 为啥? 后面我会提到。
首先想到的方案:穷举所有情况,判定是否有解。
根据题目,他有各种限制条件!行列和斜线。
题目要求,每一行每一列和对角线的,这个【五位素数】的各个数字的和,是有限制的,假设为tot.
首先,我们可以先得到10000~99999之间所有【5位素数】各个数字和等于tot素数找出来。 用字典树存起来。 为何要字典树呢? 因为方便啊!
求一个五位数,各位数字和(个位,十位,百位……的和)
inline int weihe(int k) //求k这个五位数,各个数字的和
{
int ans = 0;
while (k)
{
ans += k % 10;
k/=10;
}
return ans;
}
字典树:
struct node //字典树
{
int a;
bool flag;
node *next[10];
int sou[15];
node(int k)
{
a = k;
memset(next, NULL, sizeof(next));
flag = false;
}
node(){
a = -1;
memset(next, NULL, sizeof(next));
flag = false;
}
void make() //字典树构造类dancing link
{
int i, t;
memset(sou, -1, sizeof(sou));
for (i = 0; i <= 9; ++ i)
if (next[i])
{
sou[10] = i;
t = i;
break;
}
for ( ++ i;i <= 9; ++ i)
if (next[i])
{
sou[t] = i;
t = i;
}
}
}Tnull, *root = &Tnull, Tnull2, *root2 = &Tnull2;
注意到字典树的make()函数么!
没错!这是一个核心优化!让程序从运行7秒加速到1秒3!!这个优化很好想,但是没想到优化效果如此高。
因为字典树的next[0], next[1]...next[9]这几节点,很多节点是空的,所以用链表的想法,直接用sou[10]表示要搜的第一个next[sou[10]], 假如sou[10] = k; 那么第二个要搜的节点就是n