03 2012 档案
摘要:/*题目: 很裸的次小生成树题,要求先给出最小生成树的值,若有不连通的输出-1, 接着需要输出次小生成树的值分析: 可以选择prim或kruskal算法做,我的做法是用prim做的,具体看代码注释*/#include <iostream>#include <cstring>#include <cstdio>using namespace std;#define X 503#define INF 10000000int path[X][X],map[X][X],dis[X],pre[X],n,m;bool use[X],visit[X][X];int prim
阅读全文
摘要:/*有向图的传递闭包问题,只要顶点的入度或出度大于n/2,即可判断它不符合中间点,即答案加一,而求它的入度或出度的话,可以用有向图的传递闭包floyd算法来做,时间复杂度为O(n^3)*/#include <iostream>#include <cstring>#include <cstdio>using namespace std;#define X 100int map[X][X],n,m;void floyd(){ for(int k=1;k<=n;k++) //floyd算法求传递闭包 for(int i=1;i<=n;i++) for(
阅读全文
摘要:模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 1049 1050 1057 1062 1063 1064 1070 1073 1075 1082 1083 1084 1088 1106 1107 1113 1117 1119 1128 1129 1144 1148 1157 1161 1170 1172 1177 1197 1200 1201 1202 1205 1209 1212(大数取模) 1216(链表)1218 1219 1225 1228
阅读全文
摘要:/*機器手臂有以下幾種合法搬積木的方式(a和b是積木的編號):move a onto b在將a搬到b上之前,先將a和b上的積木放回原來的位置(例如:1就放回1的最開始位罝)move a over b在將a搬到b所在的那堆積木之上之前,先將a上的積木放回原來的位罝(b所在的那堆積木不動)pile a onto b將a本身和其上的積木一起放到b上,在搬之前b上方的積木放回原位pile a over b將a本身和其上的積木一起搬到到b所在的那堆積木之上quit動作結束*/#include <iostream>#include <cstring>#include <str
阅读全文
摘要://ACM ICPC Central European Regional 1997/*简单的栈的应用,可惜WA了好几次poj上要把最后的while后的cout<<endl;去掉*/#include <iostream>#include <stack>#include <cstdio>using namespace std;const int X = 1005;int a[X],b[X];int main(){ freopen("sum.in","r",stdin); freopen("sum.ou
阅读全文
摘要:/*(x1,y2) ____________ (x2,y2) | | | | | | |____________|(x1,y1) (x2,y1)在上面的矩形中,本题用树状数组来计算的,所以sum(x2,y2)计算的是它的左下方所有的手机用户数,但是它多算了sum(x2,y1)以下的以及sum(x1,y2)以下的,若减掉即ans = sum(x2,y2) - sum(x2,y1) -sum(x1,y2)的话,又减多了sum(x1,y1)部分,那只好加上这一部分了。另外,在update(),sum()时,无非算多了一维,很容易理解的,具体看代码,新学到了 i -...
阅读全文
摘要:/*晕,弄少了九位数的那段据说偶数位的话,除了11是回文素数以外,其他均可被11整除并且是合数,然后就枚举1位3位5位7位9位数的数,然后判断是否为素数即可*/#include <iostream>#include <cmath>using namespace std;long long a,b;bool judge(long long x){ for(int i=2;i<=(int)sqrt(x*1.0);i++) if(x%i==0) return false; return true;}void solve(){ long long ans; if(a<
阅读全文
摘要:/*题目: 是说学生0怀疑有SARS病,跟他接触过的俱乐部的所有人以及他接触过的人再与别人接触, 都有可能有SARS病,要你求出给出的所有俱乐部人的名单,要你求出所有的嫌疑犯。。。分析: 用并查集的方法做,具体实现是先定义n个森林,然后再把同一的人所在的森林合并在一起, 而并查集的改善方法有两种,我的使用的是压缩路径的方法*/#include <iostream>#include <cstring>#include <cstdio>using namespace std;const int X = 30010;int parent[X],a[X],Rank[
阅读全文
摘要:/*题目: 给出n个商店,每个商店有初始化的商品数量,现在有两种指令: 0 x y 连锁店x的商品数量变化值为y,y > 0商品数量增加, y < 0减少 1 i j 输出编号在[i,j]区间内的连锁店中商品数量为素数的有多少家 当指令为1时,求给出 i到j的商品数量为素数的商店的数目分析: 用树状数组做,只不过在update()处改动一下,并且注意到有可能改动完后和改动前 均为素数的情况,所以用visit[]数组记录此前是否为素数,另外需要注意的是当初始 化时即为奇数的话,当时就要初始化数组c[]以及visit[]数组*/#include <iostream>#inc
阅读全文
摘要:/*哈弗曼编码,比如权值为 a:1 b:1 c:2 d:3 e:5 f:6 的树 1.开始时由最小的两个数 a:1 b:1组成一棵树 2.接着由新的最小的两个数 2 c:2 d:3 e:5 f:6 中的 2 c:2组成新的树 3.接着由最小的两个数 4 d:3 组成新的树 4.接着由最小的两个数 e:5 f:6 组成一棵树 5.接着由最小的两个数 7 11 组成一棵树(最终形成) 6.算最小的编码总长:= 18 + 7 + 11 + 4 + 2 = 42 2 4 7 11 18 / \ / \ / \ / \ / \ a b2 c 4 de f 7 11 / \ / \/ \ /...
阅读全文
摘要:编辑器加载中.../*题目: 问能否组成一棵树分析: 注意到该树为有向树,入度不能大于一,同时所有节点都应该能指向根, 可以用并查集查找是否有共同的根,有的话就不是树了,注意此时应该 要判断是否有两个入度,就不能用压缩路径的并查集,并且只能把出度 的点付给入度的点的并查集数组(不知道我自己理解是否有错。。。), 最后要判断是不是森林,可以用第一个点来检验与后面所有的节点是否 有交集,只要有一个没有的话,就是森林而不是树 (空树也是树。。。) 从poj中的discuss中找到 1: 0 0 空树是一棵树 2: 1 1 0 0 不是树 不能自己指向自己 3: 1 2 1 2 0 0 不是树....
阅读全文
摘要:/*分析: 由于有些物品存在多个,可以用数组逐一保存下,然后用01背包问题求解, 但是这样太耗时间,会造成time limitted,可以用二进制形式保存拥有多个 的物品,这样可以考虑完全并且比较省时间*/#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define X 100005int dp[X],cash[X];int main(){ freopen("poj1276.in","r",stdin); freope
阅读全文
摘要://这题用高精度乘法算#include <iostream>#include <cstring>using namespace std;#define X 140void multiply(int num[],int a[],int m) //高精度乘法运算{ int s[X]; memset(s,0,sizeof(s)); int i,j; for(j=0;j<m;j++) for(i=0;i<126;i++) s[i+j] += num[i]*a[j]; //核心算法,把乘完的结果保存到数组s[]中 int carry = 0; //表进位 for(i=
阅读全文
摘要:#include <iostream>#include <cstdio>#include <string>using namespace std;#define X 305string s;int map[X][X],color[X],n,x,y,len,c,ans;bool check(int a,int col) //检查顶点a的颜色能否涂成col{ for(int i=1;i<=n;i++) if(map[a][i]&&color[i]==col) //相邻节点颜色与他一样,不行 return false; return true
阅读全文
摘要:编辑器加载中.../*题目: 问周游一圈后能不能换钱得到利润分析: 有向图是否处在负环问题,因为涉及每个顶点都可能存在负环, 直接用flord算法做即可*/#include <iostream>#include <string>#include <cstring>using namespace std;#define X 35string city[X],s1,s2;double map[X][X];int main(){ freopen("sum.in","r",stdin); freopen("sum.o
阅读全文
摘要:/*题目: 象棋中马如何走到指定地点分析: BFS题,分8个方向搜就行 具体的图型可以看看poj1915题的8个方向,理解BFS后很容易写出*/#include <iostream>#include <cstring>#include <queue>#include <cstdio>using namespace std;#define X 310int sx,sy,ex,ey,n;bool visit[X][X];struct node{ int x,y,step;};bool check(int x,int y){ if(x<1||y&
阅读全文
摘要:此方法是看了别人的题解的,利用像dp的思维做,f[m][n] = f[m][n-1]+f[m-n][n],其中f[m][n]表示m个水果n个盘子时总的放的方法数,因为f[m][n]总可以通过有空盘子或者没空盘子来放,f[m][n-1]表示有空盘子的情况,而f[m-n][n]表示没有空盘子的情况,思路非常巧妙#include <iostream>using namespace std;int ans;int dfs(int m,int n){ if(m==1) return 1; if(m<0) return 0; if(n==1) return 1; return dfs(m
阅读全文
摘要:/*题目: 填充数独游戏分析: 先从后面开始搜,也就是从第八十个开始搜 1、如果一个小的方格内已经包含了非零的数,则继续向下搜 2、如果一个小的方格内是一个零数,也就是还没有放入相应的数,则对其从零到九开始尝试 3、对每一个数的尝试,检查其合法性:在其所在的3*3方格内是否合适;在此行是否合适,在此列是否合适 4、如果经过以上条件可以的话那么这个数字就可以放在此小方格上,然后继续进行搜索。*/#include <iostream>#include <cstring>#include <string>using namespace std;int a[10][
阅读全文
摘要:终于靠自己A了一道比较难的题了(n_n)据说是减枝题,不过我的剪枝还有待提高,以下做法竟然差点time limitted(985MS)我自己的思路:DFS搜索题,按当前需要构造的分数值,当前分母的总乘积,已经有了的个数,上一层分母值进行搜索,当遇到已经有了的个数等于a时,返回假,否则从上一层的分母值开始为下一个分数进行检查是否满足条件,满足的话答案加一#include <iostream>#include <cmath>using namespace std;#define X 1e-8int p,q,a,n;int ans;bool dfs(double cs,int
阅读全文
摘要:周赛的题目,思想011111111111000111111111111111转换为011111122222000333111444222555然后按该位置的高度向两边扩展,当遇到小于该高度时,停止扩展,然后用右边的下标减左边的下标加一,再乘以当前的高度即为所求,dp的实现是在计算第二个矩阵时用到的,只是简单的h[i,j] = h[i-1,j]+1 (map[i][j]=='F')#include <cstring>#include <iostream>#include <string>using namespace std;#define X
阅读全文
摘要:输入括号输入:(注意:据说有空行,用getline()或者gets()输入)([(]([(((])))[]]]]])))(((要求输出最小要加入的括号数目之后的匹配括号串分析: 经典dp题,如果用dp自底向上的递推做的话,比较麻烦,其实用记忆化做很简单, 每次递归前加上判断是否已经计算过即可减少计算量,相当于dfs里的剪枝,代码如下#include <iostream>#include <string>#include <cstring>using namespace std;#define X 205#define INF 1000int dp[X][X]
阅读全文
摘要:此题跟之前的括号最小添加数目一样的做法,只不过某些地方稍加改动,可以看看前一篇的括号最小添加数#include <iostream>#include <string>#include <cstring>using namespace std;#define X 210#define INF 1000string s;int dp[X][X];int f(int i,int j) //记忆化dp{ if(dp[i][j]!=-1) //如果已经算过,直接结束 return dp[i][j]; else if(i>=j) return 0; int ans
阅读全文
摘要:题目:输入括号输入:(注意有空行,用getline()或者gets()输入)([(]([(((])))[]]]]])))(((要求输出最小要加入的括号数目分析: 经典dp题,如果用dp自底向上的递推做的话,比较麻烦,其实用记忆化做很简单, 每次递归前加上判断是否已经计算过即可减少计算量,相当于dfs里的剪枝,代码如下#include <iostream>#include <string>#include <cstring>using namespace std;#define X 205#define INF 1000int dp[X][X];string
阅读全文
摘要:分析: 贪心算法 当n为偶数时,例如:1 2 3 4 5 6,可知,分开的两支队伍为 1 3 5与2 4 6时等待时间最小。 当n为奇数时,例如1 2 3 4 5时,可知,分开的两支队伍为 1 3 4与2 4时总等待时间最小,若n为奇数时,所以每次总把最小的数放在最长的队列中时, 总等待时间最小#include <iostream>#include <cstdio>#include <algorithm>using namespace std;#define X 1005int d[X],n,ans;int main(){ freopen("sum
阅读全文
摘要:分析: 扩展的欧几里德算法,ax+by=gcd(a,b),若gcd(a,b)!=1,输出-1,否则,用扩展的欧几里德算法求出 最小的x与y即可,注意到 当存在0时,若有1输出1,否则输出-1; 当存在1,若有2输出1,否则输出2(因为直接a-a+1即可) 当上面都不满足时,直接用扩展的欧几里德算法求出x,在解方程求出y,两绝对值相加减一即可#include <cmath>#include <iostream>using namespace std;long long ex_gcd(long long a,long long b,long long &x,long
阅读全文
摘要:题目: 给出邮递员每天要走的路线,要你求出最小的消耗分析: 注意每一个字符串如three,表示邮递员起始于t,要走到e,而此时所消耗为字符串的长度, 你要确定跑遍所有这些街道所需的最小旅程。旅程结束时必须回到起点的路口。注意到题目给出 奇数度的顶点不超过两个,就是说有且只有两个,或者一个没有,所以根据欧拉回路可知,如果 没有奇数顶点的话,直接输出所输入的总字符串长度即可。如果有两个奇数顶点的话,还要加上 两个顶点之间的距离,就是说可能要求任意两顶点之间的距离,涉及到题目的输入规模最大不过为 26,用floyd算法即可O(n^3)#include <iostream>#include
阅读全文
摘要:做完整数划分那题后,现在感觉这道题很简单,状态转移方程为dp[i][j] = dp[i][i] j>i = dp[i-j][j-1]+dp[i][j-1]建议看看我的博客上的hoj1402题#include <iostream>#include <cstring>using namespace std;#define X 510long long dp[X][X],n;void init(){ memset(dp,0,sizeof(dp)); for(int i=1;i<X;i++) //初始化 { dp[1][i] = 1; dp[0][i] = 1; }
阅读全文
摘要:/*整数划分是一个经典的问题。希望这道题会对你的组合数学的解题能力有所帮助。Input 每组输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n)Output 对于每组输入,请输出六行。 第一行: 将n划分成若干正整数之和的划分数。 第二行: 将n划分成k个正整数之和的划分数。 第三行: 将n划分成最大数不超过k的划分数。 第四行: 将n划分成若干奇正整数之和的划分数。 第五行: 将n划分成若干不同整数之和的划分数。 第六行: 打印一个空行。第一行和第三行: 对于第一行和第三行,根据状态转移方程很容易写出: dp[i][j] = dp[i][i]
阅读全文
摘要:题目: 求最长的重量上升且iq下降的子序列分析: 其实就是最长上升子序列的变形,其实很简单,先按重量按照由小到大进行排序, 然后就是LIS的事,打印路径的话,用数组path[]记录后面的位置,利用 递归实现打印(具体参考算法导论)#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define X 1005int dp[X],path[X];struct node{ int iq,w,id; //记录iq,重量
阅读全文
摘要:简单枚举#include <iostream>#include <string>using namespace std;int main(){ freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); string s; while(cin>>s,s!="*") { int len = s.size(); bool flag = true; for(int i=1;i<len-1&&a
阅读全文
摘要:/*题目: 求最少时间从(0,0)走到(4,4)的路径分析: 纯粹BFS题目,不过需要打印路径,可以用数组记录当前的坐标的上一个坐标, 因为BFS构造出一棵BFS最优生成树,每一个节点的父母节点都是唯一的,具体 参考算法导论。。。*/#include <iostream>#include <cstring>#include <cstdio>#include <queue>using namespace std;#define X 6int map[X][X],pre[X][X];bool visit[X][X];struct node{ int
阅读全文
摘要:编辑器加载中...题目: 给出一些树名,问每一棵树的所占的比例分析: 就是给树按字典序排序,并输出他们所占的比例,由于本题涉及的树名比较多,可以采用 二分搜索树来做,然后按照中序遍历即可#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define X 50int cnt;struct node //树的结构体{ int id; //储存个数的 char name[X]; //储存名字 node *rchild; //右子树 node *lchild; //左
阅读全文