2015-04-17 23:53:52
思路:模拟退火启蒙题...
缩小系数定为了:0.7。由于这题具有单调性,所以其实不用模拟退火去随机化多个起点,用“爬山算法”即可,只用一个起点,让它“爬”到最优解。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <ctime> 11 #include <string> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 #define MEM(a,b) memset(a,b,sizeof(a)) 17 #define REP(i,n) for(int i=0;i<(n);++i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 20 #define MP(a,b) make_pair(a,b) 21 22 typedef long long ll; 23 typedef pair<int,int> pii; 24 const int INF = (1 << 30) - 1; 25 const int MAXN = 110; 26 const double cof = 0.7; 27 28 int N; 29 double X[MAXN],Y[MAXN]; 30 int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; 31 32 double Dis(int a1,int b1,int a2,int b2){ 33 return sqrt(1.0*(a1-a2)*(a1-a2) + (b1-b2)*(b1-b2)); 34 } 35 36 double Cal(int a,int b){ 37 double res = 0; 38 REP(i,N) res += Dis(a,b,X[i],Y[i]); 39 return res; 40 } 41 42 int main(){ 43 srand((unsigned)time(NULL)); 44 while(scanf("%d",&N) != EOF){ 45 REP(i,N) scanf("%lf%lf",&X[i],&Y[i]); 46 int sx = 0,sy = 0,step = 1000; 47 double ans = Cal(sx,sy); 48 while(step >= 1){ 49 while(1){ 50 bool mov = false; 51 REP(k,4){ 52 int tx = sx + dir[k][0] * step; 53 int ty = sy + dir[k][1] * step; 54 if(tx < 0 || tx > 10000 || ty < 0 || ty > 10000) continue; 55 double tmp = Cal(tx,ty); 56 if(tmp < ans){ 57 ans = tmp; 58 sx = tx; 59 sy = ty; 60 mov = true; 61 } 62 } 63 if(mov == false) break; 64 } 65 step *= cof; 66 } 67 printf("%.f\n",ans); 68 } 69 return 0; 70 }