hdoj 1109 粒子群优化算法(PSO)
2015-10-02 18:50
429 查看
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1109
大意是在一个平面内有很多点,我们要在平面内找到一个点,使得这个点与其他点之间的最短距离最大。
看到别人都是用的模拟退火或者是爬山法,感觉模拟退火与粒子群优化算法相比更容易陷入局部最优,所以还是用PSO算法比较心安。
利用粒子群优化算法,设置了20个粒子和100代即可AC。代码如下:
#include <iostream>
#include <ctime>
#include <iomanip>
#include <cmath>
using namespace std;
#define num_parcle 20
double w = 0.8;
int n;
int gen = 100;
struct parcle
{
double x, y;
double dis;
double vx,vy;
};
struct point
{
double x,y;
};
template <class X ,class Y>
double distance(X& p,Y& q)
{
return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
point point_list[1000];
parcle now[num_parcle+1];
parcle last[num_parcle+1];
parcle history[num_parcle+1];
int max_x,max_y;
double valuate(parcle& cv)
{
if(cv.x<0||cv.y<0||cv.x>max_x||cv.y>max_y){
return 0;
}
double dis = distance(cv,point_list[0]);
double temp;
for(int i(1);i<n;i++)
{
temp = distance(cv,point_list[i]);
if(temp<dis)
dis = temp;
}
return dis;
}
void initi()
{
now[0].dis = 0;
for(int i(1);i<=num_parcle;i++)
{
history[i].x=now[i].x = rand()%10000/10000.0*max_x;
history[i].y=now[i].y = rand()%10000/10000.0*max_y;
history[i].dis=now[i].dis = valuate(now[i]);
history[i].vx = now[i].vx = rand()%10000/10000.0*max_y*0.3;
history[i].vy = now[i].vy = rand()%10000/10000.0*max_x*0.3;
if(now[i].dis > now[0].dis)
now[0]=now[i];
}
}
void update()
{
double temp;
for(int i(1);i<=num_parcle;i++)
{
now[i].x = now[i].x+now[i].vx;
now[i].y = now[i].y+now[i].vy;
temp = valuate(now[i]);
now[i].dis = temp;
if(temp>history[i].dis)
{
history[i].dis = temp;
history[i].x = now[i].x;
history[i].y = now[i].y;
}
if(temp>now[0].dis)
{
now[0].dis = temp;
now[0].x = now[i].x;
now[0].y = now[i].y;
}
now[i].vx = w*now[i].vx + 2*rand()%1000/1000.0*(now[0].x-now[i].x)+2*rand()%1000/1000.0*(history[i].x-now[i].x);
now[i].vy = w*now[i].vy + 2*rand()%1000/1000.0*(now[0].y-now[i].y)+2*rand()%1000/1000.0*(history[i].y-now[i].y);
}
}
int main()
{
int t;
cin >> t;
srand(time(NULL));
while(t--)
{
cin >> max_x>>max_y;
cin >> n;
for(int i(0);i<n;i++)
{
cin >> point_list[i].x>>point_list[i].y;
}
initi();
w = 0.8;
for(int j(0);j<gen;j++)
{
w = 0.2+0.6*(gen-j)/gen;
update();
}
cout << "The safest point is ("<<setprecision(1)<<fixed<<now[0].x<<", "<<setprecision(1)<<fixed<<now[0].y<<")."<<endl;
}
return 0;
}
大意是在一个平面内有很多点,我们要在平面内找到一个点,使得这个点与其他点之间的最短距离最大。
看到别人都是用的模拟退火或者是爬山法,感觉模拟退火与粒子群优化算法相比更容易陷入局部最优,所以还是用PSO算法比较心安。
利用粒子群优化算法,设置了20个粒子和100代即可AC。代码如下:
#include <iostream>
#include <ctime>
#include <iomanip>
#include <cmath>
using namespace std;
#define num_parcle 20
double w = 0.8;
int n;
int gen = 100;
struct parcle
{
double x, y;
double dis;
double vx,vy;
};
struct point
{
double x,y;
};
template <class X ,class Y>
double distance(X& p,Y& q)
{
return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
point point_list[1000];
parcle now[num_parcle+1];
parcle last[num_parcle+1];
parcle history[num_parcle+1];
int max_x,max_y;
double valuate(parcle& cv)
{
if(cv.x<0||cv.y<0||cv.x>max_x||cv.y>max_y){
return 0;
}
double dis = distance(cv,point_list[0]);
double temp;
for(int i(1);i<n;i++)
{
temp = distance(cv,point_list[i]);
if(temp<dis)
dis = temp;
}
return dis;
}
void initi()
{
now[0].dis = 0;
for(int i(1);i<=num_parcle;i++)
{
history[i].x=now[i].x = rand()%10000/10000.0*max_x;
history[i].y=now[i].y = rand()%10000/10000.0*max_y;
history[i].dis=now[i].dis = valuate(now[i]);
history[i].vx = now[i].vx = rand()%10000/10000.0*max_y*0.3;
history[i].vy = now[i].vy = rand()%10000/10000.0*max_x*0.3;
if(now[i].dis > now[0].dis)
now[0]=now[i];
}
}
void update()
{
double temp;
for(int i(1);i<=num_parcle;i++)
{
now[i].x = now[i].x+now[i].vx;
now[i].y = now[i].y+now[i].vy;
temp = valuate(now[i]);
now[i].dis = temp;
if(temp>history[i].dis)
{
history[i].dis = temp;
history[i].x = now[i].x;
history[i].y = now[i].y;
}
if(temp>now[0].dis)
{
now[0].dis = temp;
now[0].x = now[i].x;
now[0].y = now[i].y;
}
now[i].vx = w*now[i].vx + 2*rand()%1000/1000.0*(now[0].x-now[i].x)+2*rand()%1000/1000.0*(history[i].x-now[i].x);
now[i].vy = w*now[i].vy + 2*rand()%1000/1000.0*(now[0].y-now[i].y)+2*rand()%1000/1000.0*(history[i].y-now[i].y);
}
}
int main()
{
int t;
cin >> t;
srand(time(NULL));
while(t--)
{
cin >> max_x>>max_y;
cin >> n;
for(int i(0);i<n;i++)
{
cin >> point_list[i].x>>point_list[i].y;
}
initi();
w = 0.8;
for(int j(0);j<gen;j++)
{
w = 0.2+0.6*(gen-j)/gen;
update();
}
cout << "The safest point is ("<<setprecision(1)<<fixed<<now[0].x<<", "<<setprecision(1)<<fixed<<now[0].y<<")."<<endl;
}
return 0;
}
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- 2015 Multi-University Training Contest 6 Solutions
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- POJ ACM 1002
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- ACM题库以及培养策略