05 2012 档案
摘要:标准PSO算法的C语言实现。测试函数为y=x*sin(10*PI*x)+2,x取值范围[-1,2],求最大值。View Code 1 /* 2 用粒子群算法求函数最值测试 3 测试函数为 y=x*sin(10*pi*x)+2 4 x取值范围[-1, 2] 5 */ 6 #include <stdio.h> 7 #include <math.h> 8 #include <time.h> 9 #include <stdlib.h>10 11 #define MAX(a,b) ((a)>(b)?(a):(b))12 #define PI 3.14
阅读全文
摘要:最近在写遗传算法求TSP时看到了grefenstette编码,于是想起了这个题目,这题我原来是用线段树写的C语言提交的,用时157ms,刚用树状数组+二分写用C++提交只跑了47ms,感觉快了不少。这题数学模型是:现有一个1到n的一个被打乱的排列,告诉你每个数的左边有多少个数比它小,显然第一个数左边没有比它小的数,求每个位置上的数。grefenstette编码差不多,只是把左边改成了右边再加1,例如:8 6 7 5 3 4 1 2编码后是:8 6 6 5 3 3 1 1View Code 1 #include <stdio.h> 2 #include <string.h>
阅读全文
摘要:最近在做人工智能的课设,碰到一个与TSP类似的问题,今天尝试了一下用遗传算法求解TSP,下面是我碰到的问题以及我的一些想法:1.如何对个体进行编码?TSP问题的实质是求一个最短的哈密顿回路,如果将城市标号为0,1,2...n-1,那么TSP的一个解就是一个圆排列,等价于一个规定了起点的排列,所以容易想到可以用顺序编码方式,即用一个数组保存旅游顺序。2.如何快速初始化种群?根据上述编码方式,种群初始化就是产生一系列随机排列,c++有一个函数rand_shuffle(V.begin(),V.end())可以打乱一个排列,用这个可以实现种群的快速初始化。3.如何交叉?这个问题可以说是遗传算法求TSP
阅读全文
摘要:之前用matlab写过遗传算法,但从没用c实现过,今天老师布置了人工智能的课设,为了温故下学过的遗传算法,于是有了下面的代码……下面的代码是求y=x*sin(10*pi*x)+2 (-1<=x<=2)的(近似)最大值,但稍作修改即可求其他函数的最值。View Code 1 /* 2 用遗传算法求y=x*sin(10*pi*x)+2的最大值 -1=<x<=2 3 精确到6位小数 4 pow(2,21)<3*1000000<pow(2,22) 5 编码的二进制长度为22 6 */ 7 #include <stdio.h> 8 #include <
阅读全文
摘要:BFS基础题View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #define N 201 5 #define INF 0x7fffffff 6 using namespace std; 7 queue<int> Q; 8 int d[N],t[N],n,a,b,cur,next; 9 char inq[N];10 void bfs()11 {12 for(int i=1;i<=n;i++) t[i]=INF;13 memset(inq,0,si
阅读全文
摘要:题目大意:给定n个正整数,问能否分成4组,且每组的和相等。分析:这题就是sticks那题的简化版。思路一样。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <vector> 5 #define N 20 6 using namespace std; 7 vector<int> edge[4]; 8 int len[N],n,sum; 9 char vis[N],yes;10 int cmp(const void*
阅读全文
摘要:题目数学模型:给定n个正整数,现要将这n个数分成k组,且满足每组的和都相等。求最多能分多少组。这题是经典的剪枝搜索题,原题来自PKU。下面的程序虽然AC了,但是跑不动POJ中discuss中的那组BT数据。View Code 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <vector> 5 #define MAX(a,b) ((a)>(b)?(a):(b)) 6 #define N 64 7 using namespace std;
阅读全文
摘要:跟"非常可乐"那题差不多,只是多了一个打印倒水步骤。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #define N 1001 5 #define MIN(a,b) ((a)<(b)?(a):(b)) 6 using namespace std; 7 typedef struct node 8 { 9 int v[2],t,d;10 }node;11 node cur,next;12 queue<node> Q;13 n
阅读全文
摘要:题目大意:英雄打怪,英雄有n个咒语,每个咒语能对怪造成一定的伤害,且只能使用一次,咒语使用的时机不同,伤害不同,具体表现为,当怪的体力小于某个特定值m时,伤害会加倍。每条咒语描述为(a,m),表示怪的体力大于m时伤害为a,其他时间为2*a。问能不能将怪打死,若能输出最少使用的咒语数,否则输出"-1"。当怪的体力小于或等于0时即认为怪死了。分析:要求最少的次数,很容易想到使用BFS,但用DFS的关键在于状态的判重,这题可以将已经使用的咒语列表构成状态,判重时不好处理。若使用迭代加深搜索IDS则不需判重,只是时间可能要多一点。因为n最大不超过10,即最大深度为10,肯定不会超时
阅读全文
摘要:题目大意:这题跟HDOJ"非常可乐"那题很像,用状态空间搜索即可。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #define N 101 5 #define MIN(a,b) ((a)<(b)?(a):(b)) 6 using namespace std; 7 typedef struct node 8 { 9 int v[2],t;10 }node;11 node cur,next;12 queue<node> Q;
阅读全文
摘要:题目模型:给定3个无刻度容器,容器的容积均为正整数,初始状态为第一个容器装满水,其它2个空着,问是否能将第一个容器中的水平分,若能输出最少操作步数,否则输出"NO".分析:典型的状态空间搜索题,要求最少步数,可以用BFS,将3个容器中中的水量组合定义为状态,倒水操作会造成状态转移。目标状态为某两个容器中水量相等且总和为总水量。一个小的优化是当总水量为奇数时,直接输出"NO".View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4
阅读全文
摘要:题目的模型:在一个图中,给定一系列目标结点,求从起点出发经过所有目标结点的最短距离。分析:由于目标结点数目最大为7,所以可以暴力搜索过,枚举经过目标结点的排列,然后计算选择最优的。计算距离时需要用floyd预处理任意2结点之间的最短距离。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #define N 31 4 #define MIN(a,b) ((a)<(b)?(a):(b)) 5 #define INF 0x7fffffff 6 int d[N][N],t[N],a[N],n,m,cnt,ans;
阅读全文
摘要:题目大意:跟01背包模型有点像,区别在于01背包对选取的物品个数没有要求,而这题给出了选的个数。N最大为20,所以可以暴力过。经测试N最大好像是21,定义成20会WAView Code 1 #include <stdio.h> 2 #define N 21 3 #define INF 0x7fffffff 4 int v[N],w[N],n,m,cnt,vmax,wmax; 5 void dfs(int k,int vsum,int wsum) 6 { 7 if(cnt==m) 8 { 9 if(wsum<=wmax && vsum>vmax) vmax
阅读全文
摘要:题目大意:给定一组单词(均为小写英文字母),每个单词表示能将其首字母变成尾字母,例如"go"表示能将'g'变成'o',问同过给定的单词能否将'b'变成'm'。分析:先建立有向图,然后对图进行DFS。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #define N 60000000 4 char s[N],vis[26]; 5 bool g[26][26]; 6 bool read_case() 7 { 8 int n; 9
阅读全文
摘要:经典的DFS,素数环问题。题目大意:将从1开始的前n个自然数排成一个圈,使得任意相邻的两个数的和是素数。给定n,按字典序打印结果。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #define N 20 4 int a[N],n,cnt; 5 char is_p[40],vis[N]; 6 void init() 7 { 8 memset(is_p,0,sizeof(is_p)); 9 is_p[2]=1;10 is_p[3]=1;11 is_p[5]=1;12 is_p[7]=1;13 is_p[11]=.
阅读全文
摘要:BFS题,走三维迷宫。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #define N 50 5 using namespace std; 6 typedef struct node 7 { 8 int x,y,z; 9 }node;10 queue<node> Q;11 node cur,next;12 int dx[6]={1,-1,0,0,0,0};13 int dy[6]={0,0,1,-1,0,0};14 int dz[6]={0,0,
阅读全文
摘要:BFS题,数学模型如下:对于一个01序列(长度小于20),定义翻转操作为:选定序列中的一位,将其取反,并将其左右相邻的位(如果存在)取反,现给定一个初始序列,求最少需操作多少次使得序列变成全0序列。分析:序列状态可用一个32位整数表示,状态数目最多为220,所以搜索不会超时,翻转操作可用异或运算来表示。需注意的是,写好后别忘了测试n=1的情况。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <queue> 5 using nam
阅读全文
摘要:典型的搜索题目,将1,2,3,4...8填入上图A,B,C...H中,相邻的字母中的两个数不能相邻。现给定一种初始状态,求能否完成上述要求,若方案唯一,则依次输出完成后A,B,C...H中的数。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #define N 9 5 using namespace std; 6 vector<int> g[N]; 7 int a[N],vis[N],ans[N]; 8 void init() 9 {10 g[1
阅读全文
摘要:水题……View Code 1 #include <stdio.h> 2 #include <string.h> 3 #define N 11 4 char g[N][N]; 5 int t[N][N],n,m,k,cnt; 6 int dx[128],dy[128]; 7 int main() 8 { 9 int i,j;10 dx['E']=0,dx['W']=0;11 dx['S']=1,dx['N']=-1;12 dy['E']=1,dy['W']=-1;13 dy[
阅读全文
摘要:简单bfs题。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #define N 150000 5 using namespace std; 6 queue<int>q; 7 int n,k,t[N]; 8 void bfs() 9 {10 int i;11 memset(t,-1,sizeof(t));12 while(!q.empty()) q.pop();13 t[n]=0;14 q.push(n);15 while(!q.empty())1
阅读全文
摘要:简单搜索题。View Code 1 #include <stdio.h> 2 #define N 100 3 int dx[4]={0,0,1,-1}; 4 int dy[4]={1,-1,0,0}; 5 char g[N][N],n,m,cnt; 6 void dfs(int i,int j) 7 { 8 int ni,nj,d; 9 for(d=0;d<4;d++)10 {11 ni=i+dx[d];12 nj=j+dy[d];13 if(ni<0 || nj<0 || ni>=n || nj>=m || g[ni][nj]!='#'
阅读全文
摘要:简单搜索题。将能走到的地方走一下即可。View Code 1 #include <stdio.h> 2 #define N 20 3 using namespace std; 4 int dx[4]={0,0,1,-1}; 5 int dy[4]={1,-1,0,0}; 6 char g[N][N]; 7 int n,m,cnt; 8 void dfs(int i,int j) 9 {10 int ni,nj,d;11 for(d=0;d<4;d++)12 {13 ni=i+dx[d];14 nj=j+dy[d];15 if(ni<0 || nj<0 ||...
阅读全文
摘要:题目大意:给定一个1-n的排列,规定一种操作,每次只能交换相邻的两个数,求至少进行多少次操作,能将给定的初始态转为目标态,目标态定义为序列中除1外任何一个数都比其左边相邻的那个数大(如果存在),1的左边相邻的数只能是n或者没有。分析:先考虑简单的情况,将初始态转为1,2,3...n。注意到1,2,3...n的逆序数为0,对任何一个序列进行一次上述操作逆序数会增1或减1,如果能保证每次操作都使逆序数减1,那么最少的操作次数便是逆序数,事实正是如此,下面简单证明:当一个序列的逆序数大于0时,则必存在a,b使得a在b的左边且a>b,如果a和b相邻,则交换a,b即可,如果a和b不相邻,则必存在c
阅读全文
摘要:题目链接多维动态规划好题题目大意:给定一个5行9列的中国象棋棋盘(一半),棋盘上红方只剩一个已过河的卒,现黑方让红方连续走k步,求红方最多能吃掉黑方多少棋子。k<=100分析:直接搜索的话肯定会超时(指数级别的复杂度),可以考虑根据卒的位置和其他棋子是否被吃掉来设计状态进行动态规划,关键在于状态的设计,因为卒只能向前冲不能后退,所以后面的行不影响结果,而前面的行中的棋子仍处于初始状态,只有当前行中的棋子的状态需要保存,可以用dp[i][j][k][left][right]表示卒位于i行j列还可以走k步,当前行最左走到left,最右走到right时最多能吃掉多少棋子,状态设计出来了,状态转
阅读全文
摘要:题目链接经典的8数码问题,不要求是最少步数。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #define N 362881 5 #define ABS(x) ((x)>0?(x):(-(x))) 6 using namespace std; 7 const int dx[4]={0,0,1,-1}; 8 const int dy[4]={1,-1,0,0}; 9 char DIR[4]={'r','l','d&#
阅读全文
摘要:题目链接题目大意:给定一棵树,每个结点有一个值,求一棵含k个结点的子树,使子树的值最大。(树的值为所含结点的值的和)分析:n最大为100,定义状态dp[u][k]为以结点u为根结点且含k个结点的子树的最大值。用左二子右兄弟来存树,不难写出状态转移方程。纠结之处在于使用memset(dp,-1,sizeof(dp))就WA,改成memset(dp,0xff,sizeof(dp))就AC了。其中还有好几次CE莫名其妙,提示信息为"Getting complication error information failed!"AC的代码 1 #include <stdio.h
阅读全文
摘要:题目链接题目大意:给定一个流量网络,网络的拓扑结构是无根树,定义A(k)以结点k为源点,其他叶子结点为汇点的最大流量,求的是A(k)的最大值(k=1,2,3……n)。分析:这题跟树形DP专题Computer那题有点像,那题是距离,这题是流量,本质还是一样。从结点k流出的流量,要么经过儿子结点流出,要么经过父亲结点流出。先DP求每个结点经过儿子结点能流出的最大流量是s[k],在DP求每个结点经过父亲结点能流出的最大流量f[k]。最后结果是MAX(s[k]+f[k]),k=1,2,3...n。s[k]=sum(MIN(s[i],wik)),i是k的儿子结点且不是叶子结点。s[k]=sum(wik)
阅读全文
摘要:题目链接这题跟Balance Act那题差不多,求图的质点。我直接将那题改了一下提交,结果PE了一次,又WA了一次,最后发现是单case,多case的提交为什么WA呢?View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #define N 16000 5 #define MAX(a,b) ((a)>(b)?(a):(b)) 6 using namespace std; 7 vector<int> g[N]; 8 int n,p[N],d[N],
阅读全文
摘要:题目大意:给定一棵树,求移除树中哪些结点后,剩下的结点最多的连通支的结点数目不超过原树总结点的一半。分析:先用dfs将无根树转为有根树,在一棵有根树中,去掉某个结点后,剩余的分支为儿子结点所在的分支和父亲结点所在的分支,取结点数目最多的一支即可。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #define N 10000 5 #define MAX(a,b) ((a)>(b)?(a):(b)) 6 using namespace std; 7 vec
阅读全文
摘要:题目链接题目大意:给定一棵树,对树中每一个结点,求其距其他结点的最远距离。分析:最初的想法是对每个结点求一次DFS,那样的话复杂度是O(N2),由于n最大可达10000,所以这个方法肯定会超时。根据树的特殊性可知,每个结点到距其最远的结点,要么通过其儿子结点到达,要么通过其父结点到达,由此想到可用树形动态规划。具体实现时,定义状态df[k],d1[k],d2[k],分别表示结点k通过父结点能到达的最远距离,通过儿子结点能到达的最远距离,通过儿子结点能到达的第二远距离。View Code 1 #include <stdio.h> 2 #include <string.h>
阅读全文
摘要:题目链接题目大意:给定一个连通无向图,每个结点有一个值,现要断开图中某条边,使得原图变成两个连通子图,且要使两个子图的值的差最小。输出最小差,若无法完成,则输出"impossible”分析:要使断开某条边后,原图变成两个连通支,则断开的边一定是桥。对图进行DFS时,得到一颗树,图中有的而树中没有的边叫回边,回边一定不是桥。由此想到可用dfs将图转化为树来做,但树中的边不一定是原图中的桥,问题关键在于桥的判断。此题还需要注意的是可能有重边。View Code 1 #include <stdio.h> 2 #include <math.h> 3 #include
阅读全文
摘要:题目链接题目大意:给定一个有向图(n<100),求最小圈。分析:任何一个圈至少有两个点,在圈中任取两个点i,j,圈的长度可以看成是d[i][j]+d[j][i],所以先用floyd求任意点对的最短距离,然后枚举点对求最小圈长。时间复杂度为O(N3)。View Code 1 #include <stdio.h> 2 #define MIN(a,b) ((a)<(b)?(a):(b)) 3 #define N 100 4 #define INF 0x7fffffff 5 int n,m; 6 int d[N][N]; 7 int main() 8 { 9 int i,j,k
阅读全文
摘要:题目链接题目大意:给定一个无向图,指定2个起点s1和s2和一个终点t,2个人分别从s1和s2出发,目的地是t,求两人的最短路径的最大公共长度(在保证两人均走最短路的前提下使两人一起走的路径最长)。分析:只要两人会合后,就一定会一起走完剩下的全程。所以大体思路是枚举可能的会合点,在判断某个点是否是可能的会合点时,判断这个点是否都是两个人的最短路径上的点即可。求最短路时用到dijkstra。View Code 1 #include <stdio.h> 2 #include <memory.h> 3 #define N 1000 4 #define INF 0x7fffff
阅读全文