最小生成树,Kruskal算法。
算法很简单,先把边排序,依次找链接不同集合的最小边,合并集合,当只有一个集合的时候结束。问题在于如何实现集合合并,学长们说合并时用并查集效率较高。我这里用不同的数字代表不同的集合,每次合并都要遍历所有集合,改变集合数字,时间复杂度O(n)。
Ege结构体中刚开始把b、d两个变量定义成了char,数据小的时候没问题,当数据大于127时就会爆掉,纠结了很久。
qsort()函数用法:void qsort(void *base, int nelem, int width, int (*fcmp)(const void *,const void *));
base是数组起始下标;
nelem是元素个数;
width是单个元素的大小;
fcmp是比较函数。

posted @ 2012-04-19 17:28 小鼠标 阅读(446) | 评论 (0)编辑 收藏
C语言中,文件读写相关的函数有很多个,但是从读写的数据形式来说可以分为两类:二进制和文本。关于文本读写函数不多说了,只要会使用格式化的输入输出fscanf()、fprintf()就基本可以解决问题。这里主要说一下二进制的文件读写函数fread()和fwrite()。
函数原型分别为:
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
size_t fread(void* buffer, size_t size, size_t count, FILE* stream);
其中
buffer是存储数据的指针
size是单个元素的大小(单位是字节)
count是元素的个数
stream是文件指针
函数的返回值是实际读取或写入元素的个数
需要注意的是打开供二进制读写的文件时读写方式后面要多加一个"b",表示二进制读写。例如打开供二进制写入的文件可以为fp = fopen("out.txt", "wb");
用二进制存储文件可以在一定程度上起到文件的保密作用。如果别人用文本编辑器打开我们存储的二进制代码,ta看到的很可能都是些乱码。这里之所以所很可能是应为如果我们存入的本来就是文本(char类型)的话,别人还是能够看到里面的内容的。这是因为char的存入是以ASCII的形式存的,这些编码能够被文本编辑器识别。但其他的类型就不行了。
我们来举一个例子:
比如int a = 64(假设int占两个字节),64的二进制为00000000 01000000,若用文本打开,编辑器会试将a显示为两个字符,一个ASCII为0的字符,和一个ASCII为64的字符。0对应的ASCII为null,没有显示;64对应的ASCII为字符@, 这是我们能看到的。
如果我们选择用文本存储a,系统不会把a看成数字,而会看成由两个字符组成的序列:'6'和'4'。'6'的ASCII为54,二进制就是00110110,'4'的ASCII为52,二进制为00110100。因此a的文本存储形式对应的二进制就是00110110 00110100(要明白,所有数据在计算机里其实都是以二进制存储的)。
当然,二进制存储文件的根本目的是为了更快速的读写数据,因为计算机“喜欢”二进制。要想给数据加密还必须有加密算法才行。
posted @ 2012-04-13 16:59 小鼠标 阅读(1641) | 评论 (1)编辑 收藏
     摘要: 题意:求出将上面的数字变成下面的数字所需的最少路数。变换方式只有“加”,“减”,“交换”三种。一道很普通的广搜题。用used[]记录各节点的层数,以及判断该结点是否被访问过(used[i] == 0 表示没有访问过。特别注意初始节点的层数为0,但它被访问过,因此要特殊处理一下。) Code highlighting prod...  阅读全文
posted @ 2012-03-29 00:02 小鼠标 阅读(162) | 评论 (0)编辑 收藏
深度加回溯,类似于八皇后问题。
#include<stdio.h>
#include
<string.h>
#include
<stdlib.h>
char mp[6][6];//map
int len;//map length
int mb;//bigesst
int mbt;//now road length
int CP(int x, int y)//canput
{
    
int i;
    i 
= y - 1;
    
while(i >= 0 && mp[x][i] != 'X')
    
{
        
if(mp[x][i] == 'O')
            
return 0;
        i
--;
    }

    i 
= y + 1;
    
while(i < len && mp[x][i] != 'X')
    
{
        
if(mp[x][i] == 'O')
            
return 0;
        i
++;
    }

    i 
= x - 1;
    
while(i >= 0 && mp[i][y] != 'X')
    
{
        
if(mp[i][y] == 'O')
            
return 0;
        i
--;
    }

    i 
= x + 1;
    
while(i < len && mp[i][y] != 'X')
    
{
        
if(mp[i][y] == 'O')
            
return 0;
        i
++;
    }

    
return 1;
}

void DFS(int n)
{
    
int i, j;
    
int x, y;
    
if(n == len * len)    
    
{
        
if(mb < mbt)
            mb 
= mbt;    
        
return ;
    }

    x 
= n / len;
    y 
= n % len;
    
if(mp[x][y] == '.' && CP(x, y))
    
{
        mp[x][y] 
= 'O';
        mbt
++;
        DFS(n 
+ 1);
        mbt
--;
        mp[x][y] 
= '.';
        
        DFS(n 
+ 1);
    }

    
else 
        DFS(n 
+ 1);
}

int main()
{
    
int i, j;
    scanf(
"%d"&len);
    getchar();
    
while(len != 0)
    
{
        
for(i = 0; i < len; i++)//read map
            gets(mp[i]);
        mbt 
= mb = 0;
        DFS(
0);

        printf(
"%d\n", mb);
        scanf(
"%d"&len);
        getchar();
    }

}

这道题跟之前走迷宫的题略有不同,走迷宫时起始点确定,当前点可走的方向确定。而这道题结束条件是判断过的格数超过总格数。
即使是合法的点也可以选择不放炮台。
posted @ 2012-03-08 23:34 小鼠标 阅读(197) | 评论 (0)编辑 收藏
这是《算法设计与分析》教材上的一道题,我们老师布置的第一道题。说的是统计出一本给定页码书中从0~9各个数字出现的次数,页码最高不差过10e9。
穷举法是很容易想到的,不过当输入过大时很耗时间。因此应该总结规律。
#include<stdio.h>
#include
<string.h>
#include
<stdlib.h>
#include
<math.h>
#define LEN 20
int bs[] = {0120300400050000600000700000080000000900000000};
int BS = 1111111111;
void StrtoNum(char *str, int *num)
{
    
int i, len;
    len 
= strlen(str);
    
*num = 0;
    
for(i = 0; i < len; i++)
        
*num = *num * 10 + str[i] - '0';
}

int Pow(int a, int b)
{
    
int i, t;
    t 
= a;
    
for(i = 0; i < b - 1; i++)
        t 
*=a;
    
return t;
}

int GetMod(int a)
{
    
return BS % Pow(10, a);
}

int main()
{
    
int i, j;
    
int nb;// now bit
    char nums[LEN];
    
int num;
    
int rs[10];// result 
    int len;
    
int mh;//most high 
    int nt;
    
while(gets(nums) != NULL)
    
{
        memset(rs, 
0sizeof(rs));
        len 
= strlen(nums);
        StrtoNum(nums, 
&num);
        
//
        
//printf("num = %d\n", num);
        
//
        mh = nums[len - 1- '0';
        
for(i = 0; i <= mh; i++)//init the lowest bit
            rs[i] = 1;
        
for( i = 1; i < len; i++)
        
{
            nb 
= len - i -1;
            mh 
= nums[nb] - '0';
            StrtoNum(
&nums[nb + 1], &nt);
            
//
            
//printf("mh = %d nt = %d\n", mh, nt);
            
//
            rs[mh] += nt + 1;//@2, mh mh
            for(j = 0; j < mh; j++)//@2 others
            {
                rs[j] 
+= Pow(10, i); 
            }

            
for(j = 0; j < 10; j++)//@1
            {
                rs[j] 
+= mh * bs[i];
            }
            
        }

        rs[
0-= GetMod(len);
        
for(i = 0; i < 10; i++)
            printf(
"%d %d\n", i, rs[i]);
    }

    
//getchar();
}

统计出只有一位数的情况是很简单的,我们来当在统计好的一个数字前面再加上位数时统计结果会怎么增加。我们可以把这个增加的值看做两部分,一部分是因高位增加导致地位数的取值范围增大而导出的,另一部分是高位本身产生的。两方面的计算都有规律可循。要特别注意0的计算。
请注意库函数pow()的返回值为double,转换为int时会有精度丢失(调试中的表现为无论数据多大,结果总跟标准答案相差1),因此这里特地写了一个Pow()函数做返回值为int的乘方计算。
posted @ 2012-03-08 19:38 小鼠标 阅读(1017) | 评论 (0)编辑 收藏
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3171
据说这道题用的是动态规划,首先把"s"看成要找的串,其次"se",其次'sev',直到"seven",只需将元串扫描5遍即可得到结果。
#include<stdio.h>
#include
<string.h>
#include
<stdlib.h>
#define LEN 10005
int main()
{
    
char s1[LEN];
    
long long  rs[6][LEN];
    
char s0[7= "@seven";
    
char s2[7= "@SEVEN";
    
int i, j;
    
int len;
    
//printf("%d\n", sizeof(long long));
    while(gets(s1) != NULL)
    
{
        memset(rs, 
0sizeof(rs));
        
for(i = 0; i < LEN; i++)
            rs[
0][i] = 1;
        len 
= strlen(s1);
        
for(i = 1; i < 6; i++)
            
for(j = 0; j < len; j++)
            
{
                
if(s1[j] == s0[i] || s1[j] == s2[i])
                    rs[i][j 
+ 1= rs[i][j] + rs[i - 1][j];
                
else
                    rs[i][j 
+ 1= rs[i][j];
            }

        printf(
"%lld\n", rs[5][len]);
        
/*for(i = 0; i < 6; i++)
        {
            for(j = 0; j < len + 2; j++)
                printf("%ld ", rs[i][j]);
            putchar(10);
        }
*/

    }

}



再次印证了我的菜鸟身份,long long 的输出格式为"%lld",为此WA了三次。
posted @ 2012-03-04 17:48 小鼠标 阅读(85) | 评论 (0)编辑 收藏
简单的走迷宫,广搜求最短路径,要把坐标搞清楚。
#include<stdio.h>
#include
<string.h>
#include
<stdlib.h>
#define LEN 14
#define QLEN 100000
typedef 
struct 
{
    
int x;
    
int y;
    
int z;
}
Point;
typedef 
struct 
{
    
int f;
    
int r;
    Point 
*p;
}
Queue;
int d[6][3=
{
    
001,
    
00-1,
    
100,
    
-100,
    
010,
    
0-10
}
;
char sp[LEN][LEN][LEN];//space map
int rl[LEN][LEN][LEN];//road length
Point bg, ed;
int N;
void BFS()
{
    
int i, j;
    Point t;
    
int x, y, z;
    
int find = 0;
    Queue q;
    q.f 
= q.r = 0;
    q.p 
= (Point*)malloc(sizeof(Point) * QLEN);
    q.p[q.f] 
= bg;
    q.r
++;
    
while(q.f != q.r && !find)
    
{
        t 
= q.p[q.f];
        q.f 
= (q.f + 1% QLEN;//DeQueue
        for(i = 0; i < 6; i++)
        
{
            x 
= t.x + d[i][0];
            y 
= t.y + d[i][1];
            z 
= t.z + d[i][2];
            
if(sp[z][y][x] == 'O')//can walk
            {
                sp[z][y][x] 
= 'X';//change mp
                rl[z][y][x] = rl[t.z][t.y][t.x] + 1;//change rl
                q.p[q.r].x = x;//EnQueue
                q.p[q.r].y = y;
                q.p[q.r].z 
= z;
                q.r 
= (q.r + 1% QLEN;
            }

            
else if(sp[z][y][x] == 'E')
            
{
                rl[z][y][x] 
= rl[t.z][t.y][t.x] + 1;//change rl
                find = 1;
            }

        }

    }

    free(q.p);
}

int main()
{
    
int i, j, k, m;
    
char s1[LEN];
    
int gard = 100;
    
while(scanf("%s%d", s1, &N) == 2 && gard--)
    
{
        getchar();
        
for(i = 1; i <= N; i++)//read space map
            for(j = 1; j <= N; j++)
            
{
                
for(k = 1; k <= N; k++
                    sp[i][j][k] 
= getchar();
                getchar();
            }


        scanf(
"%d%d%d"&bg.x, &bg.y, &bg.z);//read point 
        scanf("%d%d%d"&ed.x, &ed.y, &ed.z);
        getchar();
        gets(s1);
//read END 
        
//getchar();
        bg.x += 1;
        bg.y 
+= 1;
        bg.z 
+= 1;
        ed.x 
+= 1;
        ed.y 
+= 1;
        ed.z 
+= 1;
        sp[bg.z][bg.y][bg.x] 
= 'B';
        sp[ed.z][ed.y][ed.x] 
= 'E';

        
for(i = 0; i <= N + 1; i++)//init map
            for(j = 0; j <= N + 1; j++)
            
{
                sp[i][j][
0= sp[i][j][N + 1= sp[N + 1][i][j] = '#';
                sp[
0][i][j] = sp[i][0][j] = sp[i][N +1][j] = '#'
            }


        
for(i = 0; i < LEN; i++)//init road length
            for(j = 0; j < LEN; j++)
                
for(k = 0; k < LEN; k++)
                    rl[i][j][k] 
= 0;
        BFS();
        
if(rl[ed.z][ed.y][ed.x] != 0)
            printf(
"%d %d\n", N, rl[ed.z][ed.y][ed.x]);
        
else if(bg.x == ed.x && bg.y == ed.y && bg.z == ed.z)
            printf(
"%d 0\n", N);
        
else 
            printf(
"NO ROUTE\n");
                    
    }
    
}

这道题交了很多遍一直WA,很是郁闷。刚开始以为自己的队列没有管理好,换成STL队列问题依旧,又怀疑输出格式的问题,修改后问题依旧。最后终于看到BFS()中有一个break(写在了for循环里面),这样是跳不出while的,用标志find代替break后果然AC!
想和写之间的确有很大的差距,多些代码才是硬道理。

scanf("%s",s1)读取字符串时对前面的空白符有过滤作用,并且字符串中间的空白符将被认为字符串的结束标志,空白符不会被读入
gets(s1)读取字符串时对前面和中间的空白符都没有过滤,只有换行符才会被认为是字符串的结束标志,该换行符不被认为是字符串的一部分


posted @ 2012-03-04 12:54 小鼠标 阅读(211) | 评论 (0)编辑 收藏
     摘要: 求最短路径,最直接的广度优先搜索。 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->#include<stdio.h>#include<string.h>#include<stdlib.h>#define ...  阅读全文
posted @ 2012-03-01 18:38 小鼠标 阅读(135) | 评论 (0)编辑 收藏
深度优先搜索加回溯。之前用四叉树的记录遍历迷宫的所有路径,结果内存超限制了,请教学长之后才知道有种算法设计方法叫“回溯”,即在沿一条路深度遍历后再把走过的路标记回来,这样就能避免影响其它路径的遍历。
另外关于递归要说一点,当递归中涉及到对全局变量(比如一个全局的数组)的修改时,之前我一直存在的疑问是:如果递归式树状调用结构,那么每一时刻这个全局的数组在被谁使用呢?如果每层递归都能同时使用该数组,那数据不就乱了吗?原来虽然递归的调用可以是树状的,但是每一个时刻递归都是沿着递归树中的一条路在走,一条路走不通了才会退一步,换个子树接着走。这些都是在了解回溯之后才想通的。
#include<stdio.h>
#include
<stdlib.h>
#include
<string.h>
typedef 
struct 
{
    
char x;
    
char y;
}
Node;

int fd;//have find given length 
int T;
int len;
char mp[8][8];//map
void f(int x, int y)
{
    
if(!fd)
    
{
        
if(mp[x - 1][y] == 'D' && len + 1 == T)fd = 1;
        
else if(mp[x - 1][y] == '.')//go up
        {
            len 
++;
            mp[x 
- 1][y] = 'X';
            f(x 
- 1, y);
            len 
--;
            mp[x 
- 1][y] = '.';
        }

        
if(mp[x][y + 1== 'D' && len + 1 == T)fd = 1;
        
else if(mp[x][y + 1== '.')//go right
        {
            len 
++;
            mp[x][y 
+ 1= 'X';
            f(x, y 
+ 1);
            len 
--;
            mp[x][y 
+ 1= '.';
        }

        
if(mp[x + 1][y] == 'D' && len + 1 == T)fd = 1;
        
else if(mp[x + 1][y] == '.')//go down
        {
            len 
++;
            mp[x 
+ 1][y] = 'X';
            f(x 
+ 1, y);
            len 
--;
            mp[x 
+ 1][y] = '.';
        }

        
if(mp[x][y - 1== 'D' && len + 1 == T)fd = 1;
        
else if(mp[x][y - 1== '.')//go left
        {
            len 
++;
            mp[x][y 
- 1= 'X';
            f(x, y 
- 1);
            len 
--;
            mp[x][y 
- 1= '.';
        }

    }

}

int main()
{
    
int N, M;
    
int i, j;
    
int find;
    Node s;
    scanf(
"%d%d%d"& N, & M, & T);           
    
while(N + M + T != 0)
    
{
        
for(i = 1; i <= N; i++)//read map
            scanf("%s",&mp[i][1]);
        
for(i = 1; i <= N; i++)
            
for(j = 1; j <= M; j++)
                
if(mp[i][j] == 'X')
            
        
for(i = 0; i <= N + 1; i++)//init map
            mp[i][0= mp[i][M + 1= 'X';    
        
for(i = 1; i <= M; i++)
            mp[
0][i] = mp[N + 1][i] = 'X';
            
        find 
= 0;
        
for(i = 1; i <= N && find == 0; i++)//search start point
            for(j = 1; j<= M && find == 0; j++)
                
if(mp[i][j] == 'S')
                
{
                    s.x 
= i;
                    s.y 
= j;
                    find 
= 1;
                }
 
                
        fd 
= 0;
        len 
= 0;
        f(s.x, s.y);
        
if(fd == 1)
            puts(
"YES");
        
else
            puts(
"NO");
         
        scanf(
"%d%d%d"& N, & M, & T);
    }

}


posted @ 2012-02-28 17:14 小鼠标 阅读(184) | 评论 (0)编辑 收藏
问题的关键是题目要求没有给清楚,没有给出输入数据的范围。应该先将数字当做字符串处理。
#include<stdio.h>
#include
<string.h>
int root2(char *s)
{
    
int sum2 = 0;
    
int i, len = strlen(s);
    
for(i = 0; i < len; i++)
        sum2 
+= s[i] - '0';
    
return sum2;
    
}

long root(long n)
{
    
long sum = 0;
    
while(n)
    
{
        sum 
+= n % 10;
        n 
/= 10;
    }

    
return sum;
}

int main()
{
    
long sum;
    
char s[1000];
    gets(s);
    
while(strcmp(s, "0"))
    
{
        sum 
= root2(s);
        
while(sum / 10)
        
{
            sum 
= root(sum);
        }

        printf(
"%d\n", sum);
        gets(s);
    }

}


posted @ 2012-02-22 18:31 小鼠标 阅读(71) | 评论 (0)编辑 收藏
仅列出标题
共13页: First 5 6 7 8 9 10 11 12 13 
<2012年7月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

随笔分类(111)

随笔档案(127)

friends

最新评论

  • 1. re: 线段树
  • 是这个样子的,所以在OJ有时候“卡住”了也不要太灰心,没准真的不是自己的原因呢。
    加油,祝你好运啦!
  • --小鼠标
  • 2. re: 线段树
  • 对于编程竞赛来说,Java所需时间一般为C/C++的两倍。合理的竞赛给Java的时间限制是给C/C++的两倍。
  • --伤心的笔
  • 3. re: poj1273--网络流
  • 过来看看你。
  • --achiberx
  • 4. re: (转)ubuntu11.10无法启动无线网络的解决方法
  • 膜拜大神。。查了一个下午资料终于在这里解决了问题。。神牛说的区域赛难道是ACM区域赛。。?
  • --Hang
  • 5. re: 快速排序、线性时间选择
  • 博主,谢谢你的文章。你的方法可以很好的处理分区基准在数组中重复的情况,书上的方法遇到这种输入会堆栈溢出。书上给出了解释但给的方法貌似不简洁。
  • --lsxqw2004

阅读排行榜