POJ3253[USACO 2006 November Gold]--Fence Repair

来源:互联网 发布:宝格丽蛇头包尺寸数据 编辑:程序博客网 时间:2024/05/23 17:50

这道题总的思想就是贪心,因为每修一次的花费就是修的板的总长度,每次修就是将两块板合为一块板,所以总共要修n-1次。修的次数是一定的,所以要使总花费最小的话,只要每次修最短的两块板就行了,因此在求的过程中要时时更新和维护最小的两块板。有些同学直接想到用数组存各个板的长度,然后sort一下,之后每合成一块板就插入一下,再修改一下下标。

#include<algorithm>#include<iostream>#include<cstdio>#include<cmath>using namespace std;const int maxn=1000001;int n,a[maxn],i,j,k,b;long long sum,ans=0;int main(){    scanf("%d",&n);    int l=n;    for(i=1;i<=n;++i)scanf("%d",&a[i]);    sort(a+1,a+n+1);    k=1;    for(i=1;i<n;++i)    {        sum=a[k]+a[k+1];        ans+=sum;        k+=2;        b=k;        while(a[k]<sum&&k<=l)k++;        for(j=l+1;j>k;--j)a[j]=a[j-1];        a[k]=sum;        l++;        k=b;    }    printf("%lld\n",ans);}

这显然可以,但还有更简易的方法,有一种数据结构叫做——priority_queue(优先队列)。
想到用优先队列做这道题就基本结束了,之后只是代码的实现了,每次合成时抽出队列前两个元素,合成完再push进去,但要注意要定义成小顶堆。下面给出代码。

#include<stdio.h>#include<queue>#include<algorithm>#include<iostream>#define M 100005#define ll long longusing namespace std;int main(){    int n;        ll ans=0,x;        priority_queue<ll,vector<ll>,greater<ll> >q;        scanf("%d",&n);        for(int i=1;i<=n;i++){            cin>>x;            q.push(x);        }        while(q.size()>1){            ll x1=q.top();q.pop();            ll x2=q.top();q.pop();            ll sum=x1+x2;            ans=ans+sum;            q.push(sum);        }        cout<<ans<<endl;    return 0;}

当解题时需要维护一下变量时,可以考虑采用适当的数据结构,这道题就是一个典型的例子。

Algorithm+Data Structures=Programs
                                                                     ——Niklaus Wirth

2 0
原创粉丝点击