http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11441
6482 - Beautiful MountainsTime limit: 3.000 seconds |
一顿乱优化。。。。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long int LL; const int maxn=30030; int n; bool isprime[maxn]; LL moutain[maxn]; LL leftcost[maxn],rightcost[maxn],sum[maxn],prime[maxn],pr=0; void getPRIME() { int d; memset(isprime,1,sizeof(isprime)); for(int i=2;i<=200;i+=d) { if(i==2) d=1; else d=2; if(isprime[i]) { for(int j=i+i;j<maxn;j+=i) isprime[j]=false; } } for(int i=2;i<maxn;i++) { if(isprime[i]) prime[pr++]=i; } } int main() { getPRIME(); while(scanf("%d",&n)!=EOF&&n) { leftcost[0]=rightcost[n]=0; for(int i=1;i<=n;i++) { scanf("%I64d",moutain+i); sum[i]=sum[i-1]+moutain[i]; leftcost[i]=leftcost[i-1]+sum[i-1]; } if(sum[n]==0) {puts("0");continue;} for(int i=n-1;i>=1;i--) { rightcost[i]=rightcost[i+1]+sum[n]-sum[i]; } LL mincost=132222222000LL; for(int i=1;i<=n;i++) { ///只有1堆 LL costP,toleft,toright; int from,to,m; mincost=min(mincost,leftcost[i]+rightcost[i]); for(int j=0;prime[j]+i<=n;j++) { LL costP=0; bool flag=false; ///只有4堆 2 + P + 2 if(prime[j]==3&&i+prime[j]+4<=n) { costP=leftcost[i]+rightcost[i+prime[j]+4]; int m=(2*i+4+prime[j])>>1; from=m,to=i+2; toleft=rightcost[to]-rightcost[from]-(from-to)*(sum[n]-sum[from]); from=m+1,to=prime[j]+i+2; toright=leftcost[to]-leftcost[from]-(to-from)*sum[from-1]; if(costP+toleft+toright+moutain[i+1]+moutain[i+prime[j]+3]<mincost) { mincost=costP+toleft+toright+moutain[i+1]+moutain[i+prime[j]+3]; flag=true; } } if(flag) continue; ///只有3堆 if(isprime[prime[j]+2]&&i+prime[j]+2<=n) { costP=leftcost[i]+rightcost[i+prime[j]+2]; ///左边相隔为2右边相隔为P m=(2*i+4+prime[j])>>1; from=m,to=i+2; toleft=rightcost[to]-rightcost[from]-(from-to)*(sum[n]-sum[from]); from=m+1,to=i+prime[j]+2; toright=leftcost[to]-leftcost[from]-(to-from)*sum[from-1]; if(mincost>costP+toleft+toright+moutain[i+1]) { flag=true; mincost=costP+toleft+toright+moutain[i+1]; } ///左边间隔为P右边间隔为2 m=(2*i+prime[j])>>1; from=m,to=i; toleft=rightcost[to]-rightcost[from]-(from-to)*(sum[n]-sum[from]); from=m+1,to=i+prime[j]; toright=leftcost[to]-leftcost[from]-(to-from)*sum[from-1]; if(mincost>costP+toleft+toright+moutain[i+prime[j]+1]) { flag=true; mincost=costP+toleft+toright+moutain[i+prime[j]+1]; } } if(flag) continue; ///只有两堆而且相隔P costP=leftcost[i]+rightcost[i+prime[j]]; int m=(2*i+prime[j])>>1; int from=m,to=i; LL toleft=rightcost[to]-rightcost[from]-(from-to)*(sum[n]-sum[from]); from=m+1,to=i+prime[j]; LL toright=leftcost[to]-leftcost[from]-(to-from)*sum[from-1]; if(mincost>costP+toleft+toright) mincost=costP+toleft+toright; } } printf("%I64d\n",mincost); } return 0; }