您的位置:首页 > 其它

usaco 4.3 Letter Game 搜索

2008-08-25 13:55 281 查看
搜索题目,状态很多,需要优化:
1.优化搜索顺序:先确定对角线,因为对角线对行列的影响最大。然后每次选取已确定数字个数最多的行列进行枚举,这样最省时间
2.合理设计数据结构:假设我们需要迅速查找到第一位和第五位分别为1,3的素数集合,该如何处理?预处理是搜索问题优化的好方法,可以在搜索前将各种需要枚举的素数集合分别存起来,这样速度将会快很多
3.如果某行或者某列已经有四个数确定了,那么第五个数可以直接算出来,如果它在0到9之间并且五个数组成起来是素数的话,那么就是符合条件的

下面图示解释了枚举顺序
processing order
03332
71?28
64156
72?18
24?51

错误总结:
1.写程序的时候忘记首位不能为0的要求了,所以,对于比较长的程序,最好列一下大纲,或者把关键步骤写出来,这样不容易错
2.边界问题。计算机处理的数据一般都有上下界,所以边界要时刻考虑,负数不能作下标
3.排序出错。对关键字是数字串的数组排序,很容易出错,compare时要注意如果当前可以比较出大小,要立即返回

/*

PROG: prime3

LANG: C++

ID: heben991

*/

#include <iostream>

#include <algorithm>

using namespace std;

const int n = 5, N = 100010, PN = 200, R = 10;

int p
, p1[R][PN*R], p3[R][PN*R],

p15[R][R][PN], p124[R][R][R][PN],

p234[R][R][R][PN], p135[R][R][R][PN];

int sum;

bool del
;

char a[n+1][n+1];

struct data

{

char a[n+1][n+1];

}ans[PN*PN], *out[PN*PN];

int ans_num;

bool cmp(const data *x, const data *y)

{

int i, j;

for(i = 1; i <= n; ++i)

for(j = 1; j <= n; ++j)

{

if(x->a[i][j] < y->a[i][j]) return true;

if(x->a[i][j] > y->a[i][j]) return false; // don't forget this

}

return false;

}

void seperate(int x, char *num)

{

int i, j;

for(i = n; i >= 1; --i)

{

num[i] = x%10;

x /= 10;

}

}

void get_prime()

{

int i, j;

char num[n+1];

for(i = 2; i < N; ++i)

{

if(!del[i])

{

p[++p[0]] = i;

if(i >= 10000)

{

seperate(i, num);

if(num[1]==1 && num[5]==2)

{

printf("%d/n", i);

for(j = 1; j <= n; ++j) printf("%d ", num[j]);

exit(0);

}

int t=0;

bool zero=false;

for(j = 1; j <= n; ++j)

{

t += num[j];

if(num[j]==0) zero=1;

}

if(t == sum)

{

p1[num[1]][ ++p1[num[1]][0] ] = i;

p3[num[3]][ ++p3[num[3]][0] ] = i;

if(!zero) p15[num[1]][num[5]][ ++p15[num[1]][num[5]][0] ] = i;

// zero!!

p124[num[1]][num[2]][num[4]][ ++p124[num[1]][num[2]][num[4]][0] ] = i;

p234[num[2]][num[3]][num[4]][ ++p234[num[2]][num[3]][num[4]][0] ] = i;

p135[num[1]][num[3]][num[5]][ ++p135[num[1]][num[3]][num[5]][0] ] = i;

}

}

}

for(j = 1; j <= p[0] && p[j]*i < N; ++j)

{

del[p[j]*i] = true;

if(i%p[j]==0) break;

}

}

}

void update()

{

memcpy(ans[++ans_num].a, a, sizeof(a));

}

bool fail_row(int row)

{

int i, x=0, t=0;

for(i = 1; i <= n; ++i)

{

x *= 10;

x += a[row][i];

t += a[row][i];

}

return t!=sum || del[x];

}

bool fail_col(int col)

{

int i, x=0, t=0;

for(i = 1; i <= n; ++i)

{

x *= 10;

x += a[i][col];

t += a[i][col];

}

return t!=sum || del[x];

}

/*

process order

03332

71?28

64156

72?18

24?51

the set of prime

p1

p3

p15

p124

p234

p135

*/

int main()

{

int i, j, k, d1, d2, r1, c2, c4, r3, c1, c5;

int s[3];

char num[n+1];

freopen("prime3.in","r",stdin);

freopen("prime3.out","w",stdout);

scanf("%d%d", &sum, &a[1][1]);

get_prime();

for(d1 = 1; d1 <= p1[a[1][1]][0]; ++d1)

{

seperate(p1[a[1][1]][d1], num);

for(i = 2; i <= n; ++i)

{

a[i][i] = num[i];

}

for(d2 = 1; d2 <= p3[a[3][3]][0]; ++d2)

{

seperate(p3[a[3][3]][d2], num);

for(i = 1; i <= n; ++i)

{

a[n-i+1][i] = num[i];

}

for(r1 = 1; r1 <= p15[a[1][1]][a[1]
][0]; ++r1)

{

seperate(p15[a[1][1]][a[1]
][r1], num);

for(i = 2; i < n; ++i)

{

a[1][i] = num[i];

}

for(c2 = 1; c2 <= p124[a[1][2]][a[2][2]][a[4][2]][0]; ++c2)

{

seperate(p124[a[1][2]][a[2][2]][a[4][2]][c2], num);

a[3][2] = num[3], a[5][2] = num[5];

for(c4 = 1; c4 <= p124[a[1][4]][a[2][4]][a[4][4]][0]; ++c4)

{

seperate( p124[a[1][4]][a[2][4]][a[4][4]][c4], num);

a[3][4] = num[3], a[5][4] = num[5];

for(r3 = 1; r3 <= p234[a[3][2]][a[3][3]][a[3][4]][0]; ++r3)

{

seperate(p234[a[3][2]][a[3][3]][a[3][4]][r3], num);

a[3][1] = num[1], a[3][5] = num[5];

for(c1 = 1; c1 <= p135[a[1][1]][a[3][1]][a[5][1]][0]; ++c1)

{

seperate(p135[a[1][1]][a[3][1]][a[5][1]][c1], num);

if(num[2]==0 || num[4]==0) continue;

a[2][1] = num[2], a[4][1] = num[4];

for(c5 = 1; c5 <= p135[a[1][5]][a[3][5]][a[5][5]][0]; ++c5)

{

seperate( p135[a[1][5]][a[3][5]][a[5][5]][c5], num);

a[2][5] = num[2], a[4][5] = num[4];

a[2][3] = sum - (a[2][1]+a[2][2]+a[2][4]+a[2][5]);

if(a[2][3]<0 || a[2][3]>9 || fail_row(2)) continue;

// 0<=a[2][i]<=9 && sum(a[2])==sum && prime(a[2])

a[4][3] = sum - (a[4][1]+a[4][2]+a[4][4]+a[4][5]);

if(a[4][3]<0 || a[4][3]>9 || fail_row(4)) continue;

a[5][3] = sum - (a[1][3]+a[2][3]+a[3][3]+a[4][3]);

if(a[5][3]<0 || a[5][3]>9 || fail_col(3) || fail_row(5)) continue;

update();

}

}

}

}

}

}

}

}

for(i = 1; i <= ans_num; ++i)

{

out[i] = ans+i;

}

sort(out+1, out+ans_num+1, cmp);

for(i = 1; i <= ans_num; ++i)

{

for(j = 1; j <= n; ++j)

{

for(k = 1; k <= n; ++k)

{

printf("%d", out[i]->a[j][k]);

}

putchar('/n');

}

if(i!=ans_num) putchar('/n');

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: