1. 程式人生 > >USACO 1.3 Ski Course Design

USACO 1.3 Ski Course Design

題目描述
農民約翰的農場裡有N座山峰(1<=N<=1000),每座山都有一個在0到100之間的整數的海拔高度。在冬天,因為山上有豐富的積雪,約翰經常開辦滑雪訓練營。
不幸的是,約翰剛剛得知稅法在滑雪訓練營方面有新變化,明年開始實施。在仔細閱讀法律後,他發現如果滑雪訓練營的最高和最低的山峰海拔高度差大於17就要收稅。因此,如果他改變山峰的高度(使最高與最低的山峰海拔高度差不超過17),約翰可以避免支付稅收。
如果改變一座山x單位的高度成本是x^2單位,約翰最少需要付多少錢?約翰只願意改變整數單位的高度。
第一行:一個整數n
第二行到N+1行:每行是一座山的海拔高度
求約翰需要支付修改山海拔高度的總金額,最高和最低的山峰間高度差最多17。
解題思路:
對於這道題,一開始看到覺得應該很容易,先排個序,然貪心就可以解決了,但在貪心策略的選擇上出現了不小的問題,由於兩邊都可以向中間靠近,而且還有幾個值相同但花費不同的情況,我首先想到了雙端佇列來模擬這個過程,然後佇列兩端取值的時候總是從費最小的一個開始移動,但轉念一想,這種思路很容易就有反例,比如某一端雖然有一個花費最小的,但可能有多個,而要靠近的話必須多個都移動才會有效果。想到這裡,直接放棄了雙端佇列,轉而用陣列來解決,因為模擬這個過程的同時它的位置並不需要變化,然後就是統計兩端相同高度的所有移動一個單位的總花費,比較兩端花費的多少來決定移動哪一端即可。
題解程式碼:

#include<iostream>
#include<algorithm>
#include<deque>
using namespace std;
const int size = 1010;
typedef struct{
    int h;
    int cost;
}Solve;
Solve s[size];
int cmp(Solve a,Solve b){
    return a.h<b.h;
}
int main ()
{
    int n;
    while(cin>>n){
        for(int i=0
;i<n;i++){ cin>>s[i].h; s[i].cost=1; } sort(s,s+n,cmp); int ans=0; while(s[0].h+17<s[n-1].h){ int lcost=0,rcost=0; for(int i=0;i<n;i++) cout<<s[i].h<<" "; cout<<endl; for
(int l=0;s[l].h==s[0].h;l++) lcost+=s[l].cost; cout<<"lco:"<<lcost<<endl; for(int r=n-1;s[r].h==s[n-1].h;r--) rcost+=s[r].cost; cout<<"rco:"<<rcost<<endl; if(rcost>lcost){ ans+=lcost; int t=s[0].h; for(int l=0;s[l].h==t;l++){ s[l].cost+=2; s[l].h++; } } else{ ans+=rcost; int temp = s[n-1].h; for(int r=n-1;s[r].h==temp;r--){ s[r].cost+=2; s[r].h--; } } } cout<<ans<<endl; } return 0; }

另外,做完後發現題解的程式碼完全是用另外一種完全不同的方式實現的——列舉每一個相差為17的區間,這樣一看思路比我的要簡單好多,但我就是沒有想到……

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int N;
int h[1011];
int main(){
    freopen("skidesign.in","r",stdin);
    freopen("skidesign.out","w",stdout);
    cin >> N;
    for(int i = 0; i < N; ++i)cin >> h[i];
    int ans = 0x7FFFFFFF;
    for(int i = 0; i < 100 - 17 + 1; ++i){
        int tans = 0;
        for(int j = 0; j < N; ++j){
            if(h[j] < i)tans += (i - h[j]) * (i - h[j]);
            if(h[j] > i + 17)tans += (h[j] - i - 17) * (h[j] - i - 17);
        }
        ans = min(ans, tans);
    }
    cout << ans << endl;
    return 0;
}