淺談貪心算法2
這是我寫的貪心5章中的第2章,這一章,我想講一講在OI競賽中,貪心直覺的重要性
在考場上,因為考前作息,心理狀態甚至生理狀態,都會影響我們的成績,所以考場上分析問題的能力可能會大有縮水,所以我認為,普及組想拿一等獎,平時至少要有提高組一等獎或二等獎的水準
不過講這些好像跑題了,想在考場上寫對貪心算法,對一個選手的要求是很高的,那麽,除了可怕的數學建模能力,就真的沒有解決貪心的方法了?
答案是:直覺
https://www.luogu.org/problemnew/show/P4447
也許正如那些大神所說的,在2018的安徽省選中,我只在現場AC了兩題,一道紅題,一道綠題(也就是上面這題),平時都能切切藍題的,但是在考場上,T2(一到藍題)只拿到了40分的暴力,主要就是靠這題來扳回分數
大概一個小時,拿下了T1和T2(T2寫的暴力),看了一下題面,感覺這題還是可做的,於是開始茍正解
我們是用n表示總人數,a[]這個數組來表示某個隊員的實力的。那麽我們再把每個組裏的人數放入f[]數組,num表示當前是第幾個組,而用b[]數組表示某組最大的能力值。首先我們要將所有人按他們的能力值從小到大排序,然後再進行處理:
1、如果存在,也就是使b[j]+1=a[i],那麽可以直接插入到J組後面(這裏無需考慮是不是最大值,因為前面排過序了,所以必定為最大的),為了能讓最小的人數盡可能大,那麽應該插入到那個滿足條件人數最少的組
2、否則a[i]不可以插入到任何一組,那麽就必須新增一組
這也正是我半個小時思考後的結果,於是開始碼代碼,(為了防止出鍋),我花費了1H寫這題,因為這個問題具備單調性,所以本來準備寫完T4後再加一波二分查找的,但是T4的正解好像沒茍出來,於是就把這份代碼交上去了(以下碼風較醜,因為是考場上寫的)
#include<cstdio> #include<algorithm> using namespace std; int a[100005]; struct NODE{ int lr; int ln; }node[100005]; int main(){ //freopen ("division.in","r",stdin); //freopen ("division.out","w",stdout); int n; scanf ("%d",&n); for (int i=1;i<=n;++i){ scanf ("%d",&a[i]); } sort (a+1,a+1+n); int len=1,ans=1<<30,j; node[1].lr=a[1];node[1].ln=1; for (register int i=2;i<=n;++i){ int find1=1<<30,find2=0; for (j=1;j<=len;++j){ if ((a[i]-node[j].lr==1)||(a[i]-node[j].lr==-1)&&node[j].ln<find1){ find1=node[j].ln; find2=j; } } if (find1==(1<<30)){ ++len; node[len].ln=1; node[len].lr=a[i]; } else{ node[find2].ln++; node[find2].lr=a[i]; } } for (register int i=1;i<=len;++i){ if (node[i].ln<ans) ans=node[i].ln; } printf ("%d\n",ans); return 0; }
然後,我就在考場上切了這題,這種貪心我也不會證明,但是,直覺讓我寫對了,全班也就兩個人AC(%%%ZJFjulao)
強化直覺,就是要靠刷一些貪心來訓練直覺,當然也要有數學建模的基礎
淺談貪心算法2