给了你N个木棒,求把他们组装成一根需要的最小花费,每次只能选两根组装在一起,需要的花费为两个木棒之和,
以前遇到过把一整根切开的,那个是DP,这个则有些类似,可是大胆的猜测了一下,直接每次选取所有木棒中最短的两根,这样就可以了,那么贪心是适用的,但是数量很多,而且两根最短的组装好了得插回去,这样不可能每次都排序吧,
这题首先优先队列肯定是可以做的,
最小堆也是可以的,每次都选出堆里的最小的两个求和再放回去即可
队列本身也就是堆吧,所以差别不大,但是没用过最小堆最大堆的 所以用一次把
#include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #include<string> #include<stack> #include<map> #include<vector> #include<cmath> #include<memory.h> #include<set> #include<cctype> #include<queue> #define ll long long #define LL __int64 #define eps 1e-8 //const ll INF=9999999999999; #define inf 0xfffffff using namespace std; //vector<pair<int,int> > G; //typedef pair<int,int> P; //vector<pair<int,int>> ::iterator iter; // //map<ll,int>mp; //map<ll,int>::iterator p; LL len[20000 + 5];//小顶堆里的元素,注意len[0]代表小顶堆的元素数目 void clear() { memset(len,0,sizeof(len)); } /****构建小顶堆****/ void heap(int i) { int l = i * 2; int r = i * 2 + 1; int minn = i; if(l <= len[0] && len[l] < len[minn]) minn = l; if(r <= len[0] && len[r] < len[minn]) minn = r; if(i != minn) { int tmp = len[i]; len[i] = len[minn]; len[minn] = tmp; heap(minn); } } /******插入小顶堆*****/ void insertheap(LL x) { len[++len[0]] = x; LL tmp = len[0]; while(tmp > 1 && len[tmp] < len[tmp/2]) { int t = len[tmp]; len[tmp] = len[tmp/2]; len[tmp/2] = t; tmp >>= 1; } } LL get() { LL ans1 = len[1]; len[1] = len[len[0]];//拿走第一个以后,把堆尾的拿到堆首 len[0]--; heap(1);//重新排序 LL ans2 = len[1]; len[1] = len[len[0]]; len[0]--; heap(1); insertheap(ans1 + ans2);//取出第一小第二小的,然后相加以后再插回小顶堆 return ans1 + ans2; } int main() { int n; while(scanf("%d",&n) == 1) { clear(); for(int i=1;i<=n;i++) { scanf("%I64d",&len[i]); insertheap(len[i]); } LL ans = 0; for(int i=1;i<n;i++) ans += get();//注意i不能等于n,最后一次拼好就不用放回小顶堆里了 printf("%I64d\n",ans); } return 0; }
POJ3253 Fence Repair 小顶堆+贪心
时间: 2024-10-26 20:10:17