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;
}
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;
}
相关文章推荐
- usaco 4.3 Letter Game 搜索
- USACO-Section 4.3 Letter Game (枚举)
- USACO 4.3 Letter Game(DFS)
- USACO 4.3 Letter game
- usaco 4.3 Street Race(搜索)
- USACO 4.3 Letter Game
- USACO Section 4.3 Letter Game - 简单枚举
- 08-26 HDU3812 HDU3816 USACO 4.2~4.3 搜索剪枝,模拟,DP
- 08-27~29 HDU1010 USACO4.3~4.4 搜索剪枝,模拟,拓扑,网络流
- USACO Section 4.3 Letter Game
- USACO 4.3 Letter Game (字典树)
- usaco 4.3 Letter Game 2010.8.8
- [USACO] 从Mother’s Milk看搜索
- bzoj 2679: [Usaco2012 Open]Balanced Cow Subsets 折半搜索
- USACO 4.3 buylow
- USACO-Section1.3 Wormholes 【深度优先搜索】【暴力枚举】
- USACO-Section1.3 Wormholes [搜索]
- USACO Section 4.3 Buy low,Buy lower(LIS)
- lucene4.3简单搜索示例代码
- |BZOJ 1619|搜索|[Usaco2008 Nov]Guarding the Farm 保卫牧场