P1433 [eating cheese]

Keywords: PHP

This problem is a famous NP problem.

The positive solution should be DP, but I'm going to talk about an approximate algorithm here - climbing.

It is hoped that some dalao will pay attention to the difference between mountain climbing and simulated annealing.

Climbing is straight to the low to the high, each time take big, that is, a greedy thought.

However, simulated annealing is the probability to accept the non optimal solution.

However, it is not necessary to find out the optimal solution in one climb, but it needs to be random many times.

The greedy ideas are as follows:

  1. Random array
  2. For I = 1 - > N, j = 1 - > n enumerate two points in turn
  3. If the size decreases after I and j are exchanged, update the answer
  4. Go back to operation 1 and perform M times.

Where M is optional and proportional to your score (of course, T is too big)

Note that 2 and 3 can't be updated (exchange two to reduce the number of answers). Try to do 2 and 3 twice.

I take M=50 as A, and it's the fastest algorithm for this problem (all of the above are face to face, number, and program).

The code is as follows:

#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);
}

In fact, it can be better. After modification, no O(n) statistics is needed, and O(1) calculation is directly performed.

Complexity O(n*n*m)

\(\ color{white}{\text {but the data range is a little small... O(n) is not much faster than O(4)... (3)

Ask management to pass...

Posted by artist-ink on Thu, 31 Oct 2019 22:37:44 -0700