SERC 2013 A: Beautiful Mountains

http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11441

6482 - Beautiful Mountains

Time limit: 3.000 seconds
A:   Beautiful Mountains
Paco  loves  playing  with stacks of blocks.  He  likes to  pretend  that  they are  mountains, 
and he loves making his own terrain. Lately, he’s been restricting himself to a particular 
way  of  rearranging  the  blocks.  He  puts  all  of  his  stacks  of  blocks  into  a  straight  line. 
Then, he only changes the arrangement one block at a time. Paco does this by finding 
two adjacent stacks of blocks and moving one block from one stack to the other.
Paco has made all sorts of arrangements of his ‘mountains’ using this technique. Now he 
has decided to make his most beautiful arrangements yet. Paco finds a mountain range 
beautiful if, for every pair of mountains, the distance between the two mountains is a 
prime number (that's  every pair, not just every adjacent pair). A mountain range with a 
single stack is beautiful by default. Paco considers a stack of blocks to be a mountain if it 
has at least one block.
1 0 1
0
1 0 1 3
1
1
0
2
2
3
This diagram shows an initial configuration of the blocks, and a way  to make two stacks, 
at a distance of three apart, with 13 moves. However, with only 6 moves, Paco can make 
a beautiful arrangement with 3 stacks:
1 0 1
0
0 1 1 1
0
0
1
0
0
3 2
5
2013 ACM ICPC Southeast USA Regional Programming Contest
Page 2 of 16    2 November, 2013



一顿乱优化。。。。

#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;
}



你可能感兴趣的:(SERC 2013 A: Beautiful Mountains)