題目來源:[NWPU][2014][SRM][3]搜索與動規 A 題
http://vjudge.net/contest/view.action?cid=49918#problem/A
作者:npufz
題目:有一個很長的棒子要鋸成指定數目和指定長度的段數,每鋸一次的花費等於鋸開的棒子的長度,由於鋸斷的方案很多,請找出花費的最小值
輸入包括要鋸成棒子的段數N,和每段的長度Li,棒子的總長度爲各段的總和,1<=N<=20,000,1<=Li<=50,000
代碼:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int main()
{ int n,a[20003],i,m1,m2;
long long int sum;
cin>>n;
sum=0;
priority_queue< int ,vector<int>,greater<int> > que;
while(!que.empty()) que.pop();
for(i=0;i<n;i++)
{ scanf("%d",&a[i]);
que.push(a[i]);
}
while(que.size()>1)
{ m1=que.top();que.pop();
m2=que.top();que.pop();
sum+=(m1+m2);
que.push(m1+m2);
}
cout<<sum<<endl;
return 0;
}
反思:這個問題等價於把N段連接起來,每次連接兩段,花費爲所連接的兩段的長度的和,這正是鋸斷的一個逆過程,可以在剩下的要連接的棒子裏每次連接最短的兩段,連接 N-1次就解決了,一開始用暴力搜索的方式每次找出兩個最短的棒子,由於對步驟不夠優化,就TLE了,因爲N*N的複雜度是處在一個危險的邊緣,稍微處理不好就容易
TLE,最後不想再優化了,就用了優先隊列,複雜度降低了,就解決了