ForeignBumb [模拟退火]
Posted BearChild
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ForeignBumb [模拟退火]相关的知识,希望对你有一定的参考价值。
Bumb
Time Limit: 20 Sec Memory Limit: 512 MBDescription
Input
Output
Sample Input
4
1 5 1 4
Sample Output
5
HINT
Solution
首先,我们对于一个已知的k,可以O(n)得到Ans,这样就有60%了。
那么怎么做90%呢?老老实实写O(nlogn)是不可能的!模拟退火美滋滋!
传授一点人生的经验吧:写个对拍用于调参,由于这种题不能很单峰,显然温度变化设大一点比较容易正确,无限running + 卡时即可。
是的,没有错!BearChild就这样拿到了90%!
我们来考虑100%怎么做,显然复杂度O(n)。我们把( a[i - 1], a[i] ]看作若干个区间挂在数轴上。
然后考虑k:1->m对于答案的变化。显然可以记录cnt表示k包含的区间个数,以及sum和,这样就可以做完啦!
Code
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cmath> 8 #include<vector> 9 #include<ctime> 10 using namespace std; 11 typedef long long s64; 12 13 const int ONE = 1000005; 14 const s64 INF = 1e18; 15 16 int n, m; 17 int a[ONE]; 18 int Now, A; 19 s64 Ans = INF; 20 21 int get() 22 { 23 int res=1,Q=1;char c; 24 while( (c=getchar())<48 || c>57 ) 25 if(c==\'-\')Q=-1; 26 res=c-48; 27 while( (c=getchar())>=48 && c<=57 ) 28 res=res*10+c-48; 29 return res*Q; 30 } 31 32 void TimeE() 33 { 34 if((double)clock() / CLOCKS_PER_SEC > 0.97) 35 { 36 printf("%lld", Ans); 37 exit(0); 38 } 39 } 40 41 s64 Get(int x, int y) 42 { 43 TimeE(); 44 if(x <= y) return y - x; 45 return y + m - x; 46 } 47 48 s64 Judge(int k) 49 { 50 s64 res = 0; 51 for(int i = 2; i <= n; i++) 52 res += min(Get(a[i - 1], a[i]), 1 + Get(k, a[i])); 53 Ans = min(Ans, res); 54 return res; 55 } 56 57 double Random() {return rand() / (double)RAND_MAX;} 58 void SA(double T) 59 { 60 Now = m / 2; 61 while(T >= 1) 62 { 63 A = Now + (int)(T * (Random() * 2 - 1)); 64 if(A < 1 || A > m) A = T * Random(); 65 s64 dE = Judge(A) - Judge(Now); 66 if(dE < 0) Now = A; 67 T *= 0.92; 68 } 69 } 70 71 int main() 72 { 73 n = get(); m = get(); 74 for(int i = 1; i <= n; i++) 75 a[i] = get(); 76 if(n > 3000) {for(;;)SA(m); return 0;} 77 78 for(int i = 1; i <= m; i++) 79 Ans = min(Ans, Judge(i)); 80 81 printf("%lld", Ans); 82 }
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cmath> 8 #include<vector> 9 using namespace std; 10 typedef long long s64; 11 12 const int ONE = 1000005; 13 const s64 INF = 1e18; 14 15 int n, m; 16 int a[ONE]; 17 int L[ONE]; 18 vector <int> R[ONE]; 19 s64 Ans; 20 21 int get() 22 { 23 int res=1,Q=1;char c; 24 while( (c=getchar())<48 || c>57 ) 25 if(c==\'-\')Q=-1; 26 res=c-48; 27 while( (c=getchar())>=48 && c<=57 ) 28 res=res*10+c-48; 29 return res*Q; 30 } 31 32 int Get(int x, int y) 33 { 34 if(x <= y) return y - x; 35 return y + m - x; 36 } 37 38 int main() 39 { 40 n = get(); m = get(); 41 for(int i = 1; i <= n; i++) 42 a[i] = get(); 43 44 for(int i = 2; i <= n; i++) 45 { 46 Ans += Get(a[i - 1], a[i]); 47 L[a[i - 1]]++, R[a[i]].push_back(a[i - 1]); 48 } 49 50 s64 sum = Ans, cnt = 0; 51 52 for(int i = 2; i <= n; i++) 53 if(a[i - 1] > a[i]) 54 sum -= m - a[i - 1], cnt++; 55 56 for(int k = 2; k <= m; k++) 57 { 58 int len = R[k - 1].size(); 59 cnt = cnt + L[k - 2] - len; 60 sum -= cnt; 61 for(int i = 0; i < len; i++) 62 sum += Get(R[k - 1][i], k - 1) - 1; 63 Ans = min(Ans, sum); 64 } 65 66 printf("%lld", Ans); 67 }
以上是关于ForeignBumb [模拟退火]的主要内容,如果未能解决你的问题,请参考以下文章