A Za, A Za, Fighting...

坚信:勤能补拙

问题:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1936

思路:
第一个思路是搜索,然后直接写代码:
 1 void
 2 search(int depth, int start_from)
 3 {
 4     int i;
 5     char ch;
 6     char *ptr, *rt;
 7     if(depth == sub_len) {
 8         mark = 1;
 9         return;
10     }
11     ch = sub[depth];
12     ptr = seq;
13     while(!mark && ((rt=strchr(ptr+start_from, ch))!=NULL)) {
14         search(depth+1, rt-seq+1);
15         ptr = rt+1;
16     }
17 }
结果上述代码RE,想着即使不RE,估计也得TLE

看了别人代码,发现原来可以这么简单:
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #define MAX_LEN 100001
 5 char sub[MAX_LEN], seq[MAX_LEN];
 6 int sub_len, seq_len;
 7 
 8 int
 9 main(int argc, char **argv)
10 {
11     char *sub_p, *seq_p;
12     while(scanf("%s %s", sub, seq) != EOF) {
13         sub_len = strlen(sub);
14         seq_len = strlen(seq);
15         for(sub_p=sub, seq_p=seq; sub_p<sub+sub_len && seq_p<seq+seq_len; )
16             if(*sub_p == *seq_p) {
17                 ++sub_p;
18                 ++seq_p;
19             } else
20                 ++seq_p;
21         if(sub_p == sub+sub_len)
22             printf("Yes\n");
23         else
24             printf("No\n");
25     }
26 }

posted @ 2010-08-10 21:00 simplyzhao 阅读(114) | 评论 (0)编辑 收藏
问题:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1020

思路:
原本以为是挺简单的题,结果却始终不知道怎么搜索,艾...备受打击
虽然目前对于回溯部分的代码理解起来已经没有困难,对于每次搜索都从占用最少的列开始,还是不明白为什么...

参考:
http://www.cppblog.com/RyanWang/archive/2008/10/26/65051.aspx

代码:
 1 #define MAX_LEN 42
 2 #define MAX_SIZE 11
 3 int size, n;
 4 int used[MAX_LEN], pieces[MAX_SIZE];
 5 int flag;
 6 
 7 void
 8 dfs(int depth)
 9 {
10     int i, j, col, min_used=MAX_LEN;
11     if(depth == n) {
12         flag = 1;
13         return;
14     }
15     for(i=1; i<=size; i++)
16         if(used[i] < min_used) {
17             min_used = used[i];
18             col = i;
19         }
20     for(i=10; i>=1; i--) {
21         if(pieces[i]>0 && used[col]+i<=size && col+i-1<=size) {
22             for(j=col; j<=col+i-1; j++)
23                 if(used[j]>min_used)
24                     break;
25             if(j>col+i-1) {
26                 --pieces[i];
27                 for(j=col; j<=col+i-1; j++)
28                     used[j] += i;
29                 dfs(depth+1);
30                 for(j=col; j<=col+i-1; j++)
31                     used[j] -= i;
32                 ++pieces[i];
33             }
34         }
35     }
36 }
37 
38 int
39 main(int argc, char **argv)
40 {
41     int i, tmp, tests, sum;
42     scanf("%d"&tests);
43     while(tests--) {
44         memset(used, 0sizeof(used));
45         memset(pieces, 0sizeof(pieces));
46         flag = 0;
47         scanf("%d %d"&size, &n);
48         sum = 0;
49         for(i=0; i<n; i++) {
50             scanf("%d"&tmp);
51             ++pieces[tmp];
52             sum += (tmp*tmp);
53         }
54         if(sum == size*size)
55             dfs(0);
56         printf("%s\n", flag==1 ? "KHOOOOB!" : "HUTUTU!");
57     }
58 }
posted @ 2010-08-10 19:42 simplyzhao 阅读(225) | 评论 (0)编辑 收藏
问题:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1988

思路:
并查集的妙用
up[i]记录节点i到根节点的距离(有多少元素)
sum[i]记录以i作为根节点的树所包含的节点的个数
重点是在进行union与find操作时如何更新这两个数组,find操作所暗含路径压缩时up数组的更新较难理解

参考:
http://www.cppblog.com/longzxr/archive/2009/07/13/89974.html

代码:
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #define MAX_NUM 30005
 5 int father[MAX_NUM], up[MAX_NUM], sum[MAX_NUM];
 6 
 7 void
 8 init()
 9 {
10     int i;
11     for(i=1; i<MAX_NUM; i++) {
12         father[i] = i;
13         sum[i] = 1;
14         up[i] = 0;
15     }
16 }
17 
18 int
19 find(int item)
20 {
21     int tmp = father[item];
22     if(father[item] != item) {
23         father[item] = find(father[item]);
24         up[item] += up[tmp];
25     }
26     return father[item];
27 }
28 
29 void
30 uunion(int top, int down)
31 {
32     int a = find(top);
33     int b = find(down);
34     if(a == b)
35         return;
36     father[b] = a;
37     up[b] = sum[a];
38     sum[a] += sum[b];
39 }
40 
41 int
42 main(int argc, char **argv)
43 {
44     int p, top, down, r, cube;
45     char ch[2];
46     scanf("%d"&p);
47     init();
48     while(p--) {
49         scanf("%s", ch);
50         if(ch[0== 'M') {
51             scanf("%d %d"&top, &down);
52             uunion(top, down);
53         } else {
54             scanf("%d"&cube);
55             r = find(cube);
56             printf("%d\n", sum[r]-up[cube]-1);
57         }
58     }
59 }
posted @ 2010-08-09 14:59 simplyzhao 阅读(204) | 评论 (0)编辑 收藏
问题:
http://acm.pku.edu.cn/JudgeOnline/problem?id=2524

思路:
简单并查集,求连通分支的个数,一次AC

代码:
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #define MAX_NUM 50001
 5 int father[MAX_NUM];
 6 int rank[MAX_NUM];
 7 int total;
 8 
 9 void
10 init(int n)
11 {
12     int i;
13     for(i=1; i<=n; i++)
14         father[i] = i;
15     memset(rank, 0sizeof(rank));
16     total = n;
17 }
18 
19 int 
20 find(int item)
21 {
22     if(father[item] != item)
23         father[item] = find(father[item]);
24     return father[item];
25 }
26 
27 void
28 uunion(int item1, int item2)
29 {
30     int a = find(item1);
31     int b = find(item2);
32     if(a == b)
33         return;
34     --total;
35     if(rank[a] > rank[b])
36         father[b] = a;
37     else {
38         father[a] = b;
39         if(rank[a] == rank[b])
40             ++rank[b];
41     }
42 }
43 
44 int
45 main(int argc, char **argv)
46 {
47     int n, m, i, j, k, cnt=0;
48     while(scanf("%d %d"&n, &m)!=EOF) {
49         if(n==0 && m==0)
50             break;
51         init(n);
52         for(k=0; k<m; k++) {
53             scanf("%d %d"&i, &j);
54             uunion(i, j);
55         }
56         printf("Case %d: %d\n"++cnt, total);
57     }
58 }
posted @ 2010-08-09 09:11 simplyzhao 阅读(125) | 评论 (0)编辑 收藏
问题:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1611

思路:
话说是最基础的并查集,每个分支的根节点赋予该分支节点个数的相反数,妙...

代码:
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #define MAX_LEN 30001
 5 int parent[MAX_LEN];
 6 
 7 void
 8 init(int size)
 9 {
10     int i;
11     for(i=0; i<size; i++)
12         parent[i] = -1;
13 }
14 
15 int
16 find(int item)
17 {
18     int tmp, root = item;
19     while(parent[root] >= 0)
20         root = parent[root];
21     while(item != root) {
22         tmp = parent[item];
23         parent[item] = root;
24         item = tmp;
25     }
26     return root;
27 }
28 
29 void
30 uunion(int item1, int item2)
31 {
32     int root1 = find(item1);
33     int root2 = find(item2);
34     if(root1 != root2) {
35         if(parent[root1] < parent[root2]) { /* tree with 'root1' has more nodes */
36             parent[root1] += parent[root2];
37             parent[root2] = root1;
38         } else {
39             parent[root2] += parent[root1];
40             parent[root1] = root2;
41         }
42     }
43 }
44 
45 int
46 main(int argc, char **argv)
47 {
48     int n, m, gp, i, j, r, stu;
49     while(scanf("%d %d"&n, &m)!=EOF) {
50         if(n==0 && m==0)
51             break;
52         init(n);
53         for(i=0; i<m; i++) {
54             scanf("%d"&gp);
55             for(j=0; j<gp; j++) {
56                 scanf("%d"&stu);
57                 if(j==0)
58                     r = stu;
59                 else
60                     uunion(r, stu);
61             }
62         }
63         printf("%d\n"-parent[find(0)]);
64     }
65 }
posted @ 2010-08-07 21:51 simplyzhao 阅读(114) | 评论 (0)编辑 收藏
          出处: http://hi.baidu.com/fandywang_jlu/blog/item/b49e40893ddbb0b00f244485.html

       并查集:(union-find sets)是一种简单的用途广泛的集合. 并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作,应用很多,如其求无向图的连通分量个数、最小公共祖先、带限制的作业排序,还有最完美的应用:实现Kruskar算法求最小生成树。其实,这一部分《算法导论》讲的很精炼。

       一般采取树形结构来存储并查集,在合并操作时可以利用树的节点数(加权规则)或者利用一个rank数组来存储集合的深度下界--启发式函数,在查找操作时进行路径压缩使后续的查找操作加速。这样优化实现的并查集,空间复杂度为O(N),建立一个集合的时间复杂度为O(1),N次合并M查找的时间复杂度为O(M Alpha(N)),这里Alpha是Ackerman函数的某个反函数,在很大的范围内这个函数的值可以看成是不大于4的,所以并查集的操作可以看作是线性的。
它支持以下三种操作:
  -Union (Root1, Root2) //合并操作;把子集合Root2和子集合Root1合并.要求:Root1和 Root2互不相交,否则不执行操作.
  -Find (x) //搜索操作;搜索元素x所在的集合,并返回该集合的名字--根节点.
  -UFSets (s) //构造函数。将并查集中s个元素初始化为s个只有一个单元素的子集合.
  -对于并查集来说,每个集合用一棵树表示。
  -集合中每个元素的元素名分别存放在树的结点中,此外,树的每一个结点还有一个指向其双亲结点的指针。   
       -为简化讨论,忽略实际的集合名,仅用表示集合的树的根来标识集合。

以下给出我的两种实现:

//Abstract: UFSet                 

//Author:Lifeng Wang Fandywang

// Model One Model 2 路径压缩方式不同,合并标准不同

const int MAXSIZE = 500010;

int rank[MAXSIZE];    // 节点高度的上界

int parent[MAXSIZE]; // 根节点

int FindSet(int x){// 查找+递归的路径压缩

    if( x != parent[x] ) parent[x] = FindSet(parent[x]);

     return parent[x];

}

void Union(int root1, int root2){

     int x = FindSet(root1), y = FindSet(root2);

     if( x == y ) return ;

     if( rank[x] > rank[y] ) parent[y] = x;

     else{

         parent[x] = y;

         if( rank[x] == rank[y] ) ++rank[y];

     }

}

void Initi(void){

     memset(rank, 0, sizeof(rank));

     forint i=0; i < MAXSIZE; ++i ) parent[i] = i;

}

// Model Two

const int MAXSIZE = 30001;

int pre[MAXSIZE]; //根节点i,pre[i] = -num,其中num是该树的节点数目;

                   //非根节点j,pre[j] = k,其中kj的父节点

int Find(int x){//查找+非递归的路径压缩

     int p = x;

     while( pre[p] > 0 )    p = pre[p];

     while( x != p ){

         int temp = pre[x]; pre[x] = p; x = temp;

     }

     return x;

}

void Union(int r1, int r2){

     int a = Find(r1); int b = Find(r2);

     if( a == b ) return ;

     //加权规则合并

     if( pre[a] < pre[b] ){

         pre[a] += pre[b]; pre[b] = a;

     }

     else {

         pre[b] += pre[a]; pre[a] = b;

     }

}

void Initi(void)

{

    for( int i=0; i < N; ++i ) pre[i] = -1;

}          

并查集的一些题目和我的相关解题报告:

POJ 1611 The Suspects          最基础的并查集 
POJ 2524 Ubiquitous Religions 最基本的并查集
POJ 1182 食物链       并查集的拓展
注意: 只有一组数据;
要充分利用题意所给条件:有三类动物A,B,C,这三类动物的食物链
构成了有趣的环形。A吃B, B吃C,C吃A。也就是说:只有三个group
POJ 2492 A Bug's Life 并查集的拓展
法一:深度优先遍历
每次遍历记录下该点是男还是女,只有:男-〉女,女-〉男满足,否则,找到同性恋,结束程序。
法二:二分图匹配
法三:并查集的拓展:和1182很像,只不过这里就有两组,而1182是三组,1611无限制
POJ 1861 Network == zju_1542    并查集+自定义排序+贪心求"最小生成树"
答案不唯一,不过在ZOJ上用QSORT()和SORT()都能过,在POJ上只有SORT()才能过...
POJ 1703 Find them, Catch them 并查集的拓展
这个和
POJ 2492 A Bug's Life很像,就是把代码稍微修改了一下就AC了!
注意:And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. 就是说只有两个组。
POJ 2236 Wireless Network        并查集的应用
需要注意的地方:1、并查集;2、N的范围,可以等于1001;3、从N+1行开始,第一个输入的可以是字符串。
POJ 1988 Cube Stacking            并查集很好的应用
1、与 银河英雄传说==NOI2002 Galaxy一样;2、增加了一个数组behind[x],记录战舰x在列中的相对位置;3、详细解题报告见银河英雄传说。

JOJ 1905 Freckles   == POJ 2560 最小生成树

法一:Prim算法;法二:并查集实现Kruskar算法求最小生成树

JOJ 1966 Super Market III == PKU 1456 Supermarket 带限制的作业排序问题(贪心+并查集)

提高题目:
POJ 2912 Rochambeau
POJ 1733 Parity game    
POJ 1308 Is It A Tree?

posted @ 2010-08-07 20:28 simplyzhao 阅读(76) | 评论 (0)编辑 收藏
                出处: http://webotu.com/Article.asp?id=102

    来看一个实例,杭电1232畅通工程 http://acm.hdu.edu.cn/showproblem.php?pid=1232
    首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性问题。比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块。像畅通工程这题,问还需要修几条路,实质就是求有几个连通分支。如果是1个连通分支,说明整幅图上的点都连起来了,不用再修路了;如果是2个连通分支,则只要再修1条路,从两个分支中各选一个点,把它们连起来,那么所有的点都是连起来的了;如果是3个连通分支,则只要再修两条路……
以下面这组数据输入数据来说明
4 2
1 3
4 3
    第一行告诉你,一共有4个点,2条路。下面两行告诉你,1、3之间有条路,4、3之间有条路。那么整幅图就被分成了1-3-4和2两部分。只要再加一条路,把2和其他任意一个点连起来,畅通工程就实现了,那么这个这组数据的输出结果就是1。好了,现在编程实现这个功能吧,城镇有几百个,路有不知道多少条,而且可能有回路。
    这可如何是好?我以前也不会呀,自从用了并查集之后,嗨,效果还真好!我们全家都用它!
    并查集由一个整数型的数组和两个函数构成。数组pre[]记录了每个点的前导点是什么,函数find是查找,join是合并。
int pre[1000 ];

int find(int x)
{
//查找根节点
int r=x;
while (pre[r ]!=r)
r=pre[r ];
//路径压缩
int i=x;
int j;
while(i!=r)
{
j=pre[i ];
pre[i ]=r;
i=j;
}
//返回根节点
return r;
}
void join(int x,int y)
{
//判断x y是否连通
//如果已经连通,就不用管了
//如果不连通,就把它们所在的连通分支合并起来
    int fx=find(x),fy=find(y);
if(fx!=fy)
pre[fx ]=fy;
}
    为了解释并查集的原理,我将举一个更有爱的例子。
    话说江湖上散落着各式各样的大侠,有上千个之多。他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免不了要打一架。但大侠们有一个优点就是讲义气,绝对不打自己的朋友。而且他们信奉“朋友的朋友就是我的朋友”,只要是能通过朋友关系串联起来的,不管拐了多少个弯,都认为是自己人。这样一来,江湖上就形成了一个一个的群落,通过两两之间的朋友关系串联起来。而不在同一个群落的人,无论如何都无法通过朋友关系连起来,于是就可以放心往死了打。但是两个原本互不相识的人,如何判断是否属于一个朋友圈呢?我们可以在每个朋友圈内推举出一个比较有名望的人,作为该圈子的代表人物,这样,每个圈子就可以这样命名“齐达内朋友之队”“罗纳尔多朋友之队”……两人只要互相对一下自己的队长是不是同一个人,就可以确定敌友关系了。
    但是还有问题啊,大侠们只知道自己直接的朋友是谁,很多人压根就不认识队长,要判断自己的队长是谁,只能漫无目的的通过朋友的朋友关系问下去:“你是不是队长?你是不是队长?”这样一来,队长面子上挂不住了,而且效率太低,还有可能陷入无限循环中。于是队长下令,重新组队。队内所有人实行分等级制度,形成树状结构,我队长就是根节点,下面分别是二级队员、三级队员。每个人只要记住自己的上级是谁就行了。遇到判断敌友的时候,只要一层层向上问,直到最高层,就可以在短时间内确定队长是谁了。由于我们关心的只是两个人之间是否连通,至于他们是如何连通的,以及每个圈子内部的结构是怎样的,甚至队长是谁,并不重要。所以我们可以放任队长随意重新组队,只要不搞错敌友关系就好了。于是,门派产生了。
按此在新窗口浏览图片
    下面我们来看并查集的实现。
    int pre[1000];
    这个数组,记录了每个大侠的上级是谁。大侠们从1或者0开始编号(依据题意而定),pre[15]=3就表示15号大侠的上级是3号大侠。如果一个人的上级就是他自己,那说明他就是掌门人了,查找到此为止。也有孤家寡人自成一派的,比如欧阳锋,那么他的上级就是他自己。每个人都只认自己的上级。比如胡青牛同学只知道自己的上级是杨左使。张无忌是谁?不认识!要想知道自己的掌门是谁,只能一级级查上去。
    find这个函数就是找掌门用的,意义再清楚不过了(路径压缩算法先不论,后面再说)。
int find(int x)
{
//查找根节点
int r=x;
while (pre[r ]!=r)//如果我的上级不是掌门
r=pre[r ];//我就接着找他的上级,直到找到掌门为止。
//返回根节点
return r;//掌门驾到~~~
}
    再来看看join函数,就是在两个点之间连一条线,这样一来,原先它们所在的两个板块的所有点就都可以互通了。这在图上很好办,画条线就行了。但我们现在是用并查集来描述武林中的状况的,一共只有一个pre[]数组,该如何实现呢?
    还是举江湖的例子,假设现在武林中的形势如图所示。虚竹小和尚与周芷若MM是我非常喜欢的两个人物,他们的终极boss分别是玄慈方丈和灭绝师太,那明显就是两个阵营了。我不希望他们互相打架,就对他俩说:“你们两位拉拉勾,做好朋友吧。”他们看在我的面子上,同意了。这一同意可非同小可,整个少林和峨眉派的人就不能打架了。这么重大的变化,可如何实现呀,要改动多少地方?其实非常简单,我对玄慈方丈说:“大师,麻烦你把你的上级改为灭绝师太吧。这样一来,两派原先的所有人员的终极boss都是师太,那还打个球啊!反正我们关心的只是连通性,门派内部的结构不要紧的。”玄慈一听肯定火大了:“我靠,凭什么是我变成她手下呀,怎么不反过来?我抗议!”抗议无效,上天安排的,最大。反正谁加入谁效果是一样的,我就随手指定了一个。这段函数的意思很明白了吧?
void join(int x,int y)//我想让虚竹和周芷若做朋友
{
    int fx=find(x),fy=find(y); //虚竹的老大是玄慈,芷若MM的老大是灭绝
    if(fx!=fy) //玄慈和灭绝显然不是同一个人
          pre[fx ]=fy; //方丈只好委委屈屈地当了师太的手下啦
}
    再来看看路径压缩算法。建立门派的过程是用join函数两个人两个人地连接起来的,谁当谁的手下完全随机。最后的树状结构会变成什么胎唇样,我也完全无法预计,一字长蛇阵也有可能。这样查找的效率就会比较低下。最理想的情况就是所有人的直接上级都是掌门,一共就两级结构,只要找一次就找到掌门了。哪怕不能完全做到,也最好尽量接近。这样就产生了路径压缩算法。
    设想这样一个场景:两个互不相识的大侠碰面了,想知道能不能揍。
    于是赶紧打电话问自己的上级:“你是不是掌门?”
    上级说:“我不是呀,我的上级是谁谁谁,你问问他看看。”
    一路问下去,原来两人的最终boss都是东厂曹公公。
“哎呀呀,原来是记己人,西礼西礼,在下三营六组白面葫芦娃!”
“幸会幸会,在下九营十八组仙子狗尾巴花!”
    两人高高兴兴地手拉手喝酒去了。
    “等等等等,两位同学请留步,还有事情没完成呢!”我叫住他俩。
    “哦,对了,还要做路径压缩。”两人醒悟。
    白面葫芦娃打电话给他的上级六组长:“组长啊,我查过了,其习偶们的掌门是曹公公。不如偶们一起及接拜在曹公公手下吧,省得级别太低,以后查找掌门麻环。”
    “唔,有道理。”
    白面葫芦娃接着打电话给刚才拜访过的三营长……仙子狗尾巴花也做了同样的事情。
    这样,查询中所有涉及到的人物都聚集在曹公公的直接领导下。每次查询都做了优化处理,所以整个门派树的层数都会维持在比较低的水平上。路径压缩的代码,看得懂很好,看不懂也没关系,直接抄上用就行了。总之它所实现的功能就是这么个意思。
按此在新窗口浏览图片
    回到开头提出的问题,我的代码如下:
#include

int pre[1000 ];

int find(int x)
{
int r=x;
while (pre[r ]!=r)
r=pre[r ];
int i=x;
int j;
while(i!=r)
{
j=pre[i ];
pre[i ]=r;
i=j;
}
return r;
}
int main()
{
int n,m,p1,p2,i,total,f1,f2;
while(scanf("%d",&n) && n)//读入n,如果n为0,结束
{
//刚开始的时候,有n个城镇,一条路都没有
//那么要修n-1条路才能把它们连起来
total=n-1;
//每个点互相独立,自成一个集合,从1编号到n
//所以每个点的上级都是自己
for(i=1;i<=n;i++)
{
pre[i ]=i;
}
//共有m条路
scanf("%d",&m);
while(m--)
{
//下面这段代码,其实就是join函数,只是稍作改动以适应题目要求
//每读入一条路,看它的端点p1,p2是否已经在一个连通分支里了
scanf("%d %d",&p1,&p2);
f1=find(p1);
f2=find(p2);
//如果是不连通的,那么把这两个分支连起来
//分支的总数就减少了1,还需建的路也就减了1
if(f1!=f2)
{
pre[f2 ]=f1;
total--;
}
//如果两点已经连通了,那么这条路只是在图上增加了一个环
//对连通性没有任何影响,无视掉
}
//最后输出还要修的路条数
printf("%d\n",total);
}
return 0;
}
posted @ 2010-08-07 19:55 simplyzhao 阅读(181) | 评论 (0)编辑 收藏
     摘要:                                               A*算法解题参考:http://www.cppblog.com/lo...  阅读全文
posted @ 2010-08-07 16:10 simplyzhao 阅读(134) | 评论 (0)编辑 收藏
     摘要: 英文原版: http://www.gamedev.net/reference/articles/article2003.asp中文翻译版: http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html中文翻译版转载如下(非常感谢原作者以及翻译作者):概述虽然掌握了 A* 算法的人认为它容易,但是...  阅读全文
posted @ 2010-08-07 10:46 simplyzhao 阅读(461) | 评论 (0)编辑 收藏
     摘要: 问题:http://acm.pku.edu.cn/JudgeOnline/problem?id=1077思路:传说中经典的经典解法有: 单向BFS,双向BFS,还有A*等启发式搜索算法今天先写了前两种方法的代码,至于启发式算法待续判重: 全排列的哈希,详见: http://www.cppblog.com/Joe/archive/2010/08/06/122410.html代码(单向BFS...  阅读全文
posted @ 2010-08-06 16:36 simplyzhao 阅读(188) | 评论 (0)编辑 收藏
仅列出标题
共21页: First 12 13 14 15 16 17 18 19 20 Last 

导航

<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

统计

常用链接

留言簿(1)

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜