题解 P1433 吃奶酪
Posted dgklr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 P1433 吃奶酪相关的知识,希望对你有一定的参考价值。
这道题是一道著名的NP问题。
正解应该是DP,但我在这里讲一种近似算法——爬山。
希望某些dalao
注意一下爬山与模拟退火的区别。
爬山是直往低处往高处爬,每次取大的
,也就是一种贪心思想。
而模拟退火则是概率性
接受不优解。
不过一次爬山不一定可以找出最优解,要多次随机。
贪心思路如下:
- 随机数组
- for i=1->n,j=1->n 依次枚举两点
- 如果交换i,j后大小减小,更新答案
- 回到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)
以上是关于题解 P1433 吃奶酪的主要内容,如果未能解决你的问题,请参考以下文章