bzoj3877: [Ahoi2014&Jsoi2014]保龄球
这个题没有思路,然后看起来很可以退火的样子。。。。
然而强行退火跟sb一样。。。冷静分析了一下好像爬山捉这个更优
然鹅我不会。。。
那就瞎搞搞,本机AC贡献了7WA终于过了
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<ctime> using namespace std; int n,bk,ans; struct node{int x,y;}a[60],b[60]; bool cmp(node n1,node n2){return n1.x==n2.x?n1.y<n2.y:n1.x<n2.x;} int calc() { int ret=0; for(int i=1;i<=bk;i++) { if(a[i-1].x==10)ret+=(a[i].x+a[i].y)*2; else if(a[i-1].x+a[i-1].y==10)ret+=a[i].x*2+a[i].y; else ret+=a[i].x+a[i].y; } ans=max(ans,ret); return ret; } bool check(int i,int j) { if(a[i].x==a[j].x&&a[i].y==a[j].y)return false; if(i==n)swap(i,j); if(j==n) { if(a[j].x==10)return false; else if(a[i].x==10)return false; return true; } else return true; } double myrand(){return double(rand()%10000)/10000.0;} void annealing() { int T=1e6,sum=calc(),ddd; while(T>1e-5) { for(int i=1;i<=10;i++) { for(int x=1;x<=bk;x++) { for(int y=x+1;y<=bk;y++) if(x!=y) { if(check(x,y)) { swap(a[x],a[y]); ddd=calc(); int delta=ddd-sum; if(delta>0)sum=ddd; else swap(a[x],a[y]); T*=0.97; } } } } for(int i=1;i<=100;i++) { int x=rand()%bk+1; int y=rand()%bk+1; if(y==x){y++;if(y==n+1)y=1;} if(check(x,y)) { swap(a[x],a[y]); ddd=calc(); int delta=ddd-sum; if(delta>0||exp((double)delta/T)>myrand())sum=ddd; else swap(a[x],a[y]); T*=0.97; } } } for(int i=1;i<=20;i++) { int x=rand()%bk+1; int y=rand()%bk+1; if(y==x){y++;if(y==n+1)y=1;} if(check(x,y)) { swap(a[x],a[y]); calc(); swap(a[x],a[y]); } } } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); srand(2003); scanf("%d",&n); int x,y,i=1; while(scanf("%d%d",&a[i].x,&a[i].y)!=EOF)i++; if(i==n+2)bk=n+1; else bk=n; memcpy(b,a,sizeof(b)); ans=0; for(int u=1;u<=50;u++) { if(bk!=n)swap(a[n],a[n+1]); random_shuffle(a+1,a+bk-1+1); if(bk!=n)swap(a[n],a[n+1]); annealing(); } printf("%d\n",ans); return 0; }
pain and happy in the cruel world.