模拟退火算法解决最近最远问题

来源:互联网 发布:简单的c语言编程例题 编辑:程序博客网 时间:2024/06/06 11:39
/**    模拟退火算法真的很巧妙,而且很多问题也能转换成这个算法    这个算法最大的妙处,就是它会无序的向着你所要求的答案去    寻找,直到找到符合你的精度,概率很高    如:在一个1024*768的平面上有N 个点,现在要你在这个面上找个    点到这N个点的距离和最小,精度保留 5 位小数,有个很简单的办法    就是枚举,当然不能这么干,而模拟退火算法是处理这类问题的典范    当然它不仅仅用于处理找点,你知道,网络流就是求最大流而已,可是    却用处很多,所以说好多问题,都可一转换成模拟退火问题,尤其那些    没有确定算法,需要暴力的题,包括今年上海赛区第一题也是可以用这个    算法,不过会超时。    接着回到那个题,找一个点到这些点距离最小,模拟退火的思路就是,先任意    在这个面内找个点 st ,最好在这些点中间,设有个半径为 T,以T为半径    st 为圆心可以包括所有的N 个点。好了,下面开始找了,一般 8 个方向就够了    4个其实也差不多,对于有些题要求很高,需要更多的方向,现在就以4 个    方向分析,上下左右,st点的上下左右,st_up, st_down, st_left, st_right.    比如:st_up.x = st.x, st_up.y = st.y + T。 在这四个点里面挑个离得最近的    把st 移到这里,然后继续找直到T 的半径下再也找不到更近的点,现在T *= 0.5    继续重复上面步骤找,要知道,每次让T 减一般,很快就会减到你想要的精度。    具体看代码*/typedef struct POINT {    double x, y;}Point;int main() {    Point st, st_tmp, temp; //st_tmp, temp临时点    double T, T_MIN; // T要求把所有点覆盖,T_MIN可得到的最大精度 比如 T_MIN = 1e-6    double ans;      //目前可得的最小距离    //输入完成后    st_tmp = st;    ans = dis(st);  //dis() 函数由自己写,返回st 离所有点的距离之和    while (T > T_MIN) {        int flag;        while (flag) {            flag = 0;  //flag 的妙处            for (int i=-1; i<=1; i++)                for (int j=-1; j<=1; j++) { //八个方向,根据需要自己看着办                    temp.x = st.x + T*i;                    temp.y = st.y + T*j;                    double tmp_d = dis(temp);                    if (tmp_d < ans) {                        ans = tmp_d;                        st_tmp = temp;                        flag = 1;       //在T 半径上找到个比st 更小的点                    }                }            st = st_tmp;        //如果flag = 0,说明在T 半径的8个方向上没有比st 更优的点        }        T = 0.5 * T;    //这个也是根据情况,不过一般0.5就行了,越大越精确,速度也越慢    }    // 得到 st 为最近点,ans 为最近距离和,最远一样,改改即可    return 0;}/**    睡觉了,睡觉了,晚安*/ 收藏于 2012-01-13来自于百度空间

0 0
原创粉丝点击