随笔分类 - ACM
摘要:LIS裸题, 是严格递增的不是 不下降子序列(一开始看错了WA了好几次)O(n*n)#include <stdio.h>#include <string.h>#define N 10100int a[N];int n;void LOS(){ int dp[N],i,j,tmp,max; memset(dp,0,sizeof(dp)); dp[1]=1; max=1; for(i=2; i<=n; i++) { for(tmp=0,j=1; j<i; j++) if(a[i]>a[j] && dp[j]>tmp) ...
阅读全文
摘要:图论入门题,找多少个八连块,简单的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;
阅读全文
摘要:很简单的骑士周游问题,简单的BFS一个骑士在当前位置的话可以像8个方向走,至于骑士是怎么走的可以百度一下记录起点和终点的行列并算出它的标号(整个棋盘是8*8的,按行优先去编号从1到64,所以每个格子都会有一个唯一的编号)走了8个方向记录下每个方向的编号,每得到一个编号就判断和终点编号是否相同,是的话就已经走到了,跳出,否则的话这个格子入队另外就是记录步数,就是代码中的k另外要注意判断起点和终点相同的情况,都是输出0#include <stdio.h>#include <string.h>#include <queue>#define MAX 70using
阅读全文
摘要:判断MST的唯一性用kruskal算法实现,主要利用MST的环性质先保存所有的边在一个边集数组a中,然后单独去构建一个MST,在a中没能用上的非安全边全部放到另一个边集数组b中另外在构建MST过程要构建一个邻接表,用vextor来实现,也就是只统计MST之间的连通情况,非安全边的不统计在内例如 1 2 3(安全边) 1 3 4(非安全边)那么邻接表中,与点1相通的点有点2但是没有点3,因为点3不在MST中,所以在MST中遍历的时候是没办法直接从点1到点3的接下来是就利用MST的环性质,一个MST中不管加入那条非安全边都将会形成一个环。所以我们枚举所有的非安全边,一条非安全边e,(u,v)权值为
阅读全文
摘要:先来骂街一下………………这个OJ太神了,搞死我了,好像一定要初始化某个数组还是怎么样,至今搞不明白,我还特意搞了很多个初始化,总之有初始化就通过,没有就得吃WA,问题是那个初始化时没有必要的……………………说说算法,就是和矩阵链乘法的DP是一模一样的,用a[N]来记录n个数字,op[N]记录操作符,下标是1到N,op[i]表示a[i]后面跟的操作符,所以op[n]是没有的,赋值为"&"做个标记;如果整个表达式都是正数的话,那么很容易处理,但是数字有些是负数,我们来考虑这种情况,表达式的两部分都是负数的话相乘为正数,有可能比只用正数求的结果还大。但是我们应该使两个负数
阅读全文
摘要:最优比率生成树,网上能找到很多相关的题解和资料,这道题也不是我自己独立完成的,也是看了算法和原理才做出来的相关的知识点有二分,01分数规划,Dinkelbach算法,牛顿迭代法,查阅这些知识点都会对理解这道题有帮助并且能学到新的知识具体的题解就不写了,直接贴找回来的那个讲解,看完基本上都懂了****************************************************解法之一 0-1分数规划设x[i]等于1或0, 表示边e[i]是否属于生成树.则我们所求的比率r = ∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]), 0≤i<m.
阅读全文
摘要:最小生成树的入门题,和普通裸题有些区别,需要做出一点修改题目是要求两个岛的直接连线要大于等于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
阅读全文
摘要:拓扑排序的裸体,全裸的那种一点变形和要求都没有用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; ...
阅读全文
摘要:拓扑排序入门题,可以用STL来做,这份代码中没有用对于给出的图判断是否为有向无环图(dag),若不是,输出-1其实是按层来处理拓扑序列,算法是先找出入度为0的点,然后删除所有以这些顶点为弧尾的弧,使弧头的入度减1,然后再看下一轮的顶点中那些顶点入度为0,然后依此类推,直到所有点的入度都为0,如果最后结束的时候所有点入度为0,那么是一个dag,否则不是,输出-1,这个过程可以用队列来实现,这个代码里面没有这样做,而是每一层都重新扫描一遍,找出入度为0的顶点(之前已经纳入拓扑序列的顶点就用vis[i]=1来标记),应该用队列实现的话时间会更好另外其中是要构建邻接表的,用数组来构建,当然可以直接用S
阅读全文
摘要://拓扑排序裸题,题目要求按编号从小到大输出,要换一种思维去思考//按照数据结构课本的算法,建立邻接表,用栈实现。初始化先将入度为0的顶点入栈,然后以栈顶顶点为准,先将栈顶顶点出栈输出它的信息,然后扫描它的邻接表,没找到一个弧头就将其入度减1,减1后判断该弧头是否入度为0,是的话就入栈。直到所有顶点都出栈那么就输出了一个拓扑序列。但是这样做不能保证编号从小到大输出 为了保证从小到大输出,要用“每次都从头来过”的思想,因为题目保证一定存在拓扑序列,所以对于n个点,一定输出n次,所有外循环是次数,找到了n次,输出n个点,然后每次找,都是按照编号从1找到n,所以内循环是对应顶点的编号,从1到n,从当
阅读全文
摘要: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
阅读全文
摘要://最小生成树裸题,稠密图,用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++) { ...
阅读全文
摘要:最小生成树入门题,和纯粹的裸题有些区别,题目中有些道路已经存在,不需要建造,答案是求最后建造的总费用,不要把已经有的道路的权值算进去//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
阅读全文
摘要://DP入门题状态转移方程很容易想到//关键是构建pre数组,多少有点像KMP里面构建的next数组#include <stdio.h>#include <string.h>#define MAX 50100int a[MAX],pre[MAX],dp[MAX];int n;int main(){ int i,j,T,max; scanf("%d",&T); while(T--) { scanf("%d",&n); pre[1]=0; dp[1]=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
阅读全文
摘要://水题,直接模拟#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
阅读全文
摘要://又是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+
阅读全文
摘要://思路:一遍输入扩展前序一遍建树,在建树过程中记录该结点的水平坐标,根结点的坐标为0,往左减1,往右加1,最后会的到一个最左侧坐标L,最右侧坐标R建树之后见遍历、,遍历过程中,统计各个坐标的值并求他们的和保存在数组中,但是左侧的坐标是负值,数组没有负值,所以开一个二维数组sum[2][MAX],第一行对应右侧的坐标,从1到R,第二行对应左侧的坐标,从1到-L,也就是将左侧的坐标在统计时取绝对值,然后累加求和.思考可知建树和遍历的过程实际上相同所以干脆把遍历去掉,直接建树,建树过程中就求水平坐标并累计求和//注意输出的格式,时间也不太好,0.100上下#include <stdio.h&
阅读全文
摘要://提交通过,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(...
阅读全文
摘要://难得的1Y,完全水过去,硬生生地把式子搞出来,代码写得很差,但是数据较小而且判断//较多所以省去不少时间#include <stdio.h>#include <string.h>#include <algorithm>#define MAX 150using namespace std;char string[150],temp[150];struct elemt{ char ch; int data; int flag;}a[MAX]; //flag=0表示这个元素在运算结束之后不需要变化,1表示运算后加1,-1表示运算后减1,所以同意+flag即可i
阅读全文

浙公网安备 33010602011771号