随笔分类 -  数据结构

摘要:题目翻译:1976年“四色定理”在计算机的帮助下被证明。 这个定理宣告任何一个地图都可以只用四种颜色来填充, 并且没有相邻区域的颜色是相同的。现在让你解决一个更加简单的问题。 你必须决定给定的任意相连的图能不能够用两种颜色填充。 就是说,如果给其中一个分配一种颜色, 要让所有直接相连的两个节点不能是相同的颜色。 为了让问题更简单,你可以假设:1. 没有节点是连接向它自己的。2. 是无向图。 即如果a连接b, 那么b也是连接a的3. 图是强连接的。就是说至少有一条路径可走向所有节点。方法一:广搜BFS由题目可知,对于每个结点,所有和它相接的点必须和这个点颜色不一样。那么,很自然可以用广搜来做: 阅读全文
posted @ 2012-11-07 23:51 Titanium 阅读(242) 评论(0) 推荐(0)
摘要:搜索水题,其实就是一个图的遍历(因为放在数据结构图专题中)给你一个图,以一整行的"_________"作为这个图的结束然后"X"表示不能到达,空格是能到达的,"*"也是可以到达的,并且是一个起点,要求从所有的起点出发,能到达的地方都标记为"#"然后输出标记后的整个图,"_______"也是要输出的另外注意这个图不一定是一个矩阵,可能是不规则的,例如XXXXXXXXXX X XX * XX X XXXXXXXXXXX XX XX XXXXXX_____当然这些都是没有关系的,就直接遍历好了,已经标 阅读全文
posted @ 2012-11-02 21:37 Titanium 阅读(210) 评论(0) 推荐(0)
摘要:题意:一个三维方块,给出高长宽,并且按照从最低面一层(或者从最顶面一层)到最高一层逐层给出这个方块的信息。S表示起点E表示终点,#表示这个格子不能走, .表示这个格子能走,走的方向有6个,前后左右上下。能是否能从起点走到终点,若能输出最少的步数首先想到的DFS+剪枝,后来TLE了,才自己脑子又进水了,应该用BFS,因为剪枝的话效率不高,而且题目求最小步数,显然符合BFS的特点从起点开始,将它能走的6个方向的格子且满足条件的格子入队,满足条件是指,这个格子还在方块内,而且能走,而且没有走过一开始没有记录一个格子是否走过就TLE了,又脑子进水了显然是要记录的………………如果队中某个格子就是终点的格 阅读全文
posted @ 2012-10-30 19:34 Titanium 阅读(558) 评论(0) 推荐(0)
摘要:其实题意不是很明白,看了别人的解题报告然后按照思路来实现,最后AC了,但是对于题意还是很有问题判断是否有欧拉回路,图要连通(用并查集来处理),然后所有顶点的度数为偶数在这个博客中http://www.cnblogs.com/penseur/archive/2011/02/28/1967412.html说输入的边中要包含所有的点才是存在,但是按照这个AC代码以及网上找回来的大部分代码表明是不需要包括所有代码的例如10 28 99 8输出Possible按照这个AC代码的意思应该是前面的点可以不存在,但是一旦出现了第i个点,那么必须从第i个点到第n-1个点都存在,而且图连通,度为偶数,才存在欧拉回 阅读全文
posted @ 2012-10-29 18:04 Titanium 阅读(554) 评论(0) 推荐(0)
摘要:简单骑士周游问题,BFS,有障碍物,(可能存在无障碍物的情况),起点和终点不会相同,起点终点无障碍物若能从起点出发到终点则输出步数,否者输入不能到达#include <stdio.h>#include <string.h>#include <queue>#define N 70using namespace std;bool g[N][N];int b;int start,end;struct node{ int n,r,c,k;};queue<struct node> q;int BFS(){ int ans,i,k,R[10],C[10],F 阅读全文
posted @ 2012-10-26 10:41 Titanium 阅读(504) 评论(0) 推荐(0)
摘要:图论入门题,找多少个八连块,简单的dfs解决//给出一个m*n的矩阵,有些方格染色,一个方格的邻接方格有8个,就是它四周的八个//一个染色的方格的邻接方格中也有染色的话那么把他们看做是一起的,都归为一个八连块//题目要找这个矩阵中有多少个八连块#include <stdio.h>#include <string.h>#define N 110#define M 110bool a[M][N],vis[M][N];int m,n;void dfs(int i , int j){ if(!a[i][j] || vis[i][j]) return ; vis[i][j]=1; 阅读全文
posted @ 2012-10-24 23:37 Titanium 阅读(238) 评论(0) 推荐(0)
摘要:很简单的骑士周游问题,简单的BFS一个骑士在当前位置的话可以像8个方向走,至于骑士是怎么走的可以百度一下记录起点和终点的行列并算出它的标号(整个棋盘是8*8的,按行优先去编号从1到64,所以每个格子都会有一个唯一的编号)走了8个方向记录下每个方向的编号,每得到一个编号就判断和终点编号是否相同,是的话就已经走到了,跳出,否则的话这个格子入队另外就是记录步数,就是代码中的k另外要注意判断起点和终点相同的情况,都是输出0#include <stdio.h>#include <string.h>#include <queue>#define MAX 70using 阅读全文
posted @ 2012-10-24 09:55 Titanium 阅读(694) 评论(0) 推荐(0)
摘要:最小生成树的入门题,和普通裸题有些区别,需要做出一点修改题目是要求两个岛的直接连线要大于等于10小于等于1000而不是说任意两个岛的路径和都是要满足这个条件,否则的话,要满足任意两个岛的路径和满足这个条件还是比较麻烦的显然这道题用prim算法实现才好,因为最多有n*(n-1)/2条边用kruskal算法不好在prim模板中要修改两个地方几个,一个是初始化 for(i=1; i<=n; i++) { adj[i]=1; if(g[1][i]>=MIN) lowcoat[i]=g[1][i]; else lowcoat[i]=INF; } lowcoat[1]=0;原本是直接lowco 阅读全文
posted @ 2012-10-18 17:01 Titanium 阅读(1085) 评论(0) 推荐(0)
摘要:拓扑排序的裸体,全裸的那种一点变形和要求都没有用DFS来实现//用dfs解决拓扑排序//用一个标记数组vis来标记//0表示还没有访问过,1表示正在访问,2表示已经访问过并且存入拓扑数组#include <stdio.h>#include <string.h>#define MAX 110int g[MAX][MAX],vis[MAX];int n,m,c,top[MAX];int dfs(int u){ int v; vis[u]=1; for(v=1; v<=n; v++) if(g[u][v]) { if(vis[v]==1) return 0; ... 阅读全文
posted @ 2012-10-17 19:13 Titanium 阅读(193) 评论(0) 推荐(1)
摘要:拓扑排序入门题,可以用STL来做,这份代码中没有用对于给出的图判断是否为有向无环图(dag),若不是,输出-1其实是按层来处理拓扑序列,算法是先找出入度为0的点,然后删除所有以这些顶点为弧尾的弧,使弧头的入度减1,然后再看下一轮的顶点中那些顶点入度为0,然后依此类推,直到所有点的入度都为0,如果最后结束的时候所有点入度为0,那么是一个dag,否则不是,输出-1,这个过程可以用队列来实现,这个代码里面没有这样做,而是每一层都重新扫描一遍,找出入度为0的顶点(之前已经纳入拓扑序列的顶点就用vis[i]=1来标记),应该用队列实现的话时间会更好另外其中是要构建邻接表的,用数组来构建,当然可以直接用S 阅读全文
posted @ 2012-10-17 18:45 Titanium 阅读(908) 评论(0) 推荐(0)
摘要://拓扑排序裸题,题目要求按编号从小到大输出,要换一种思维去思考//按照数据结构课本的算法,建立邻接表,用栈实现。初始化先将入度为0的顶点入栈,然后以栈顶顶点为准,先将栈顶顶点出栈输出它的信息,然后扫描它的邻接表,没找到一个弧头就将其入度减1,减1后判断该弧头是否入度为0,是的话就入栈。直到所有顶点都出栈那么就输出了一个拓扑序列。但是这样做不能保证编号从小到大输出 为了保证从小到大输出,要用“每次都从头来过”的思想,因为题目保证一定存在拓扑序列,所以对于n个点,一定输出n次,所有外循环是次数,找到了n次,输出n个点,然后每次找,都是按照编号从1找到n,所以内循环是对应顶点的编号,从1到n,从当 阅读全文
posted @ 2012-10-16 23:48 Titanium 阅读(190) 评论(0) 推荐(0)
摘要:2012-11-23今天复习了一下并查集,然后这道题才发现当时是傻掉了,其实就是并查集找有多少个连通分量,有c个连通分量的话要把他们连起来就需要c-1条边,根本不需要kruskal算法…………………………#include <cstdio>#include <cstring>#define N 1010int p[N];int n,m;int find(int x){ return p[x]==x ? x : p[x]=find(p[x]); }int main(){ while(scanf("%d",&n) && n) { f 阅读全文
posted @ 2012-10-15 18:34 Titanium 阅读(192) 评论(0) 推荐(0)
摘要://最小生成树裸题,稠密图,用prim实现不用kruskal#include <stdio.h>#include <string.h>#define MAX 110#define INF 1000*100+10int g[MAX][MAX];int n,m;int lowcoat[MAX],adj[MAX];void Prim(){ int i,j,k,min,ans; for(i=1; i<=n; i++) lowcoat[i]=g[1][i] , adj[i]=1; lowcoat[1]=0; for(i=1; i<n; i++) { ... 阅读全文
posted @ 2012-10-15 17:40 Titanium 阅读(170) 评论(0) 推荐(0)
摘要://银行客户平均等候时间//要算等候时间和算逗留时间是不同的//t1[i]表示第i个人的到达时间,t[i]表示第i个人办理时间,t2[i]表示第i个人离开时间,time[i]表示第i个人的等候时间//我们要算平均等候时间,其实就是time数组累加求和然后除以n即可//对于第1个人,他不需要等待,来到就办理,所以等待时间为0//对于第i个人,如果他来到的时候第i-1个人刚刚离开或者已经离开,那么他也不需要等待直接办理,他的情况和第1个人是一样,等待时间为0//即time[i]=0;//如果第i个人来到,但是第i-1个人还没有离开,那么他就要等待,他的等待时间是(第i-1个人的离开时间-第i个人的 阅读全文
posted @ 2012-10-13 00:22 Titanium 阅读(1378) 评论(0) 推荐(0)
摘要:最小生成树入门题,和纯粹的裸题有些区别,题目中有些道路已经存在,不需要建造,答案是求最后建造的总费用,不要把已经有的道路的权值算进去//kruskal算法已有的边权植赋为0//用SORT排序,用并查集判断是否成环#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define INF 1236343242#define MAX 110bool vis[MAX][MAX];int p[MAX];int ans[MAX*MAX];struct edge{ in 阅读全文
posted @ 2012-10-10 23:42 Titanium 阅读(312) 评论(0) 推荐(0)
摘要://提交通过,时间0.008,本题主要是字符串处理,以及层序建树,以及前序(DFS递归)//遍历3个知识点,细节问题是字符串的处理,以及空树的处理#include <stdio.h>#include <string.h>#define MAX 40010struct tree{ char data; int l,r; //最左边的孩子下标和最右边的孩子下标 int x,y; //它自身在最开始的字符矩阵中的列和行,x是列,y是行}tree[MAX];char string[210][210];char stack[MAX]; int top,line;void inpu 阅读全文
posted @ 2012-10-05 22:55 Titanium 阅读(233) 评论(0) 推荐(0)
摘要://水题,直接模拟#include <stdio.h>#include <string.h>int string[10],x[10],level;int numnode[10]={1,2,4,8,16,32,64,128};char leaf[300];int main(){ int T=0,n,m,i,j,p,q,num,level; char ch,temp[10],ans[300]; while(scanf("%d",&n)!=EOF && n) { getchar(); T++; printf("S-Tree 阅读全文
posted @ 2012-10-05 22:54 Titanium 阅读(221) 评论(0) 推荐(0)
摘要://又是DFS,其实就是建树然后一边建一般判读,但是很多这种题都不一定真刀真枪地//把建树语句写出来,只要是这种思路即可,这样就可以减少时间#include <stdio.h>int ok;int dfs(){ int w1,d1,w2,d2; scanf("%d%d%d%d",&w1,&d1,&w2,&d2); if(w1 && w2 && d1 && d2) { if( (w1*d1) != (w2*d2) ) {ok=0; return 0;} else return (w1+ 阅读全文
posted @ 2012-10-05 22:54 Titanium 阅读(652) 评论(0) 推荐(0)
摘要://思路:一遍输入扩展前序一遍建树,在建树过程中记录该结点的水平坐标,根结点的坐标为0,往左减1,往右加1,最后会的到一个最左侧坐标L,最右侧坐标R建树之后见遍历、,遍历过程中,统计各个坐标的值并求他们的和保存在数组中,但是左侧的坐标是负值,数组没有负值,所以开一个二维数组sum[2][MAX],第一行对应右侧的坐标,从1到R,第二行对应左侧的坐标,从1到-L,也就是将左侧的坐标在统计时取绝对值,然后累加求和.思考可知建树和遍历的过程实际上相同所以干脆把遍历去掉,直接建树,建树过程中就求水平坐标并累计求和//注意输出的格式,时间也不太好,0.100上下#include <stdio.h& 阅读全文
posted @ 2012-10-05 22:52 Titanium 阅读(264) 评论(0) 推荐(0)
摘要://提交通过,0.092,不算太快,先给出代码#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX 10010#define INF 100000010struct treenode{ int data,lchild,rchild,level;};int *start,*flag;int min,leaf,pre,value;int input(int *post , int *ind){ int i,len; char ch; i=0; while(1) { if(... 阅读全文
posted @ 2012-10-05 22:51 Titanium 阅读(670) 评论(0) 推荐(0)