zoukankan      html  css  js  c++  java
  • 题解 P1433 【吃奶酪】

    这道题是一道著名的NP问题。

    正解应该是DP,但我在这里讲一种近似算法——爬山。

    希望某些dalao注意一下爬山与模拟退火的区别。

    爬山是直往低处往高处爬,每次取大的,也就是一种贪心思想。

    而模拟退火则是概率性接受不优解。

    不过一次爬山不一定可以找出最优解,要多次随机。

    贪心思路如下:

    1. 随机数组
    2. for i=1->n,j=1->n 依次枚举两点
    3. 如果交换i,j后大小减小,更新答案
    4. 回到1操作,并执行M次。

    其中M是可选的,与your score成正比关系(当然太大就T了)

    注意2,3不能保证已经无法更新(交换两个使答案减少),尽量做两次2,3。

    我取M=50就A了,并是本题最快算法(我上面的都是面♂向♂数♂据♂编♂程

    代码如下:

    #include<bits/stdc++.h>
    #define repeat(a,b,c,g) for (int a=b,abck=(g>=0?1:-1);abck*(a)<=abck*(c);a+=g)
    using namespace std;
    struct point {
        double x,y;
    }a[20];
    int n;
    double operator - (point a,point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    double calc()
    {
        double ans=0;
        repeat(i,1,n,1)
        ans += a[i-1] - a[i];
        return ans;
    }
    int main()
    {
        srand(1);
        cin >> n;
        a[0].x = 0;
        a[0].y = 0;
        repeat(i,1,n,1)
        {
        	cin >> a[i].x >> a[i].y;
        }
        double MIN = calc();
        repeat(_,1,50,1)
        {
            repeat(i,1,n,1)
            {
                swap(a[rand()%n+1],a[i]);
            }
            repeat(i,1,n,1)
                repeat(j,i+1,n,1)
                {
                    double tmp = calc();
                    MIN = min(tmp,MIN);
                    swap(a[i],a[j]);
                    double tp2 = calc();
                    if (tp2 > tmp)
                        swap(a[i],a[j]);
                    MIN = min(tp2,MIN);
                }
            repeat(i,1,n,1)
                repeat(j,i+1,n,1)
                {
                    double tmp = calc();
                    MIN = min(tmp,MIN);
                    swap(a[i],a[j]);
                    double tp2 = calc();
                    if (tp2 > tmp)
                        swap(a[i],a[j]);
                    MIN = min(tp2,MIN);
                }
        }
        printf("%.2f",MIN);
    }
    

    其实还可以更优,改过后不用再O(n)统计,直接O(1)计算

    复杂度O(n*n*m)

  • 相关阅读:
    Linux 搭建SVN server
    GREENPLUM简单介绍
    监听手机录音
    Java NIO与IO的差别和比較
    元数据驱动思考实例分析
    jQuery推断复选框是否勾选
    BitBlt介绍
    Android灭亡论之Firefox OS操作系统出现
    CEGUI添加自定义控件
    IFrame和Ajax比較
  • 原文地址:https://www.cnblogs.com/dgklr/p/11179671.html
Copyright © 2011-2022 走看看