2018/7/19 考試(tower,work,holes)

noip模擬賽,挺良心的題,考的賊爛(膜一下@來日方長大佬(sdfz rank1))ios

很少說了,看題吧數組

1.tower

題面:

鐵塔(tower.pas/c/cpp)

題目描述

Rainbow和Freda要在PoeticIsland市的一座山腳下蓋房子定居了......
蓋房子須要鋼材,幸運的是,這裏有排成一行的n座廢棄的鐵塔,從左到右編號爲1~n,其中第i座的高度爲h[i]。
Rainbow和Freda想蓋一座上面小下面大的城堡,而且城堡的層數儘量多。
所以,他們要把這些鐵塔分紅儘可能多組,每組內的鐵塔編號必須是連續的,而且從左到右各組內鐵塔的高度之和單調不減。
最後,他們會用每組鐵塔所提供的鋼材構成一層城堡。
可是Rainbow和Freda簡直弱爆了有木有,因而請你幫忙計算一下最多能分紅多少組呢?app

輸入格式:

第一行一個整數n。第二行n個整數,第i個整數表示h[i]。學習

輸出格式:

輸出一個整數,表示(n-最多能分紅的組數)。spa

思路:

正解是DP,我手打了一個貪心,20分。。。。。翻譯

貪心能夠被證實是錯的,(2,2,1,3,3,本身看一下),爆搜也會超時code

怎麼辦呢?blog

DPip

咱們要求的其實就是將原序列劃分爲多個子串get

且每個子串長度和連續不降

因此咱們能夠用前綴和預處理一下

而後開始DP

咱們要保證在最後面的合起來的數儘量的小

因此維護3個數組

dp數組,前綴和數組和最大值數組

線性轉移便可

代碼(感謝顏神)

#include<iostream> #include<cstdio> #include<cstring>
#define int long long
using namespace std; inline int get() { int n; char c; while((c=getchar())||1) { if(c>='0'&&c<='9') { break; } } n=c-'0'; while((c=getchar())||1) { if(c>='0'&&c<='9') { n=n*10+c-'0'; } else { return(n); } } } int dp[5001][5001]; int ints[5001],sums[5001]; inline int he(int l,int r) { if(l==0) { return(sums[r]); } return(sums[r]-sums[l-1]); } signed main() { // freopen("tower.in","r",stdin); // freopen("tower.out","w",stdout);
    memset(dp,128,sizeof(dp)); int n=get(); for(register int i=1;i<=n;i++) { ints[i]=get(); sums[i]=sums[i-1]+ints[i]; } for(register int i=1;i<=n;i++) { dp[i][1]=1; } for(register int j=2;j<=n;j++) { int mx=-1234567890,k=j; for(register int i=j;i<=n;i++) { while(k>1&&he(k-1,j-1)<=he(j,i)) { k--; mx=max(mx,dp[j-1][k]); } if(k<j) { dp[i][j]=mx+1; } } } int maxn=0; for(register int i=1;i<=n;i++) { maxn=max(maxn,dp[n][i]); } cout<<n-maxn<<endl; fclose(stdin); fclose(stdout); return(0); }

T2:work

題面:

工做計劃(work.pas/c/cpp)

題目描述:

Mark 在無心中瞭解到了Elf的身世。
在和James商量過以後,好心的他們打算送Elf返回故鄉。
然而,去往Gliese的飛船票價高的驚人,他們暫時還付不起這筆費用。
通過一番考慮,Mark打算去額外作一些工做來得到收入。
通過一番調查,Mark發現有N個工做能夠作。
作第i件工做所須要的時間爲Di,同時也須要一個能力值Ci才能夠去作。
每件工做均可以在任意時間開始,也能夠作任意屢次。
全部的工做給付的報酬都是一致的。
同時,有S個課程能夠參加,咱們認爲今天是第0天,第i個課程在第Mi天開始,持續時間爲Li天,課程結束以後能力值會變爲Ai。
如今Mark 的能力值爲1。
Mark 只能作工做到第T天(由於那是飛船起飛的日子)。
他想知道期限內他最多能夠作多少件工做,好決定將來的打算。
因而他找到了applepi。でも、applepiは彼女と一緒に楽しむことが大切だ,(本人翻譯:可是applepi和他的女友在一塊兒享受是很重要的)因此這個任務就交給你了。

輸入格式:

第一行包含三個空格分隔的整數T,S,N。
以後S 行,每行三個整數M,L,A,描述一個課程。
以後N 行,每行兩個整數C,D,描述一件工做。

輸出格式:

一個整數,表示Mark 最多能夠作多少件工做。

思路:

標配DP,切了1個半小時

咱們首先去重,確保每一個能力值對應的是當前能力值能作到最大的工做效率(好比說能力都是3,一個要3天另外一個要4天,我只存3天)

而後咱們開始dp

dp數組我開兩維,一維表明時間,另外一維表明能力

dp[i][j]表示在i這個位置,能力值爲j時的最大收益

若是這個位置咱們作工做,那麼咱們工做結束時的最大收益就能夠由當前+1轉移而來

若是這個位置咱們學習,那麼咱們到學習結束時的最大收益就是當前的最大收益

固然,咱們一開始要將數組賦值爲負無窮

這樣不可能的狀況能夠被自動排除

代碼:

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring>
#define rii register int i
#define rij register int j
#define inf 1<<30
using namespace std; int gz[105]; struct kc{ int fi[105],nl[105],sl; }y[10005]; int n,t,s,dp[200005][105],mnl; int main() { // freopen("wrk.in","r",stdin); // freopen("wrk.out","w",stdout);
    scanf("%d%d%d",&t,&s,&n); for(rii=1;i<=s;i++) { int ltt,kkk,lzn; scanf("%d%d%d",&ltt,&kkk,&lzn); y[ltt].sl++; y[ltt].fi[y[ltt].sl]=kkk+ltt; y[ltt].nl[y[ltt].sl]=lzn; mnl=max(mnl,lzn); } for(rii=1;i<=105;i++) { gz[i]=inf; } for(rii=1;i<=n;i++) { int ltt,kkk; scanf("%d%d",&ltt,&kkk); gz[ltt]=min(gz[ltt],kkk); } int cnt=0; for(rii=0;i<=10000;i++) { for(rij=0;j<=100;j++) { dp[i][j]=-inf; } } dp[0][1]=0; for(rii=0;i<=t-1;i++) { int minx=inf; int maxn=0; for(rij=1;j<=mnl;j++) { if(i!=0) { dp[i][j]=max(dp[i][j],dp[i-1][j]); } minx=min(minx,gz[j]); if(minx==inf) { continue; } dp[i+minx][j]=max(dp[i+minx][j],dp[i][j]+1); maxn=max(maxn,dp[i][j]); } for(rij=1;j<=y[i].sl;j++) { dp[y[i].fi[j]][y[i].nl[j]]=max(dp[y[i].fi[j]][y[i].nl[j]],maxn); } } int ans=0; for(rii=1;i<=100;i++) { ans=max(dp[t][i],ans); } cout<<ans; return 0; } 

3.holes

題面

樹洞(holes.pas/c/cpp)

題目描述

在一片棲息地上有N棵樹,每棵樹下住着一隻兔子,有M條路徑鏈接這些樹。更特殊地是,只有一棵樹有3條或更多的路徑與它相連,其它的樹只有1條或2條路徑與其相連。
換句話講,這些樹和樹之間的路徑構成一張N個點、M條邊的無向連通圖,而度數大於2的點至多有1個。
近年以來,棲息地頻繁收到人類的侵擾。
兔子們聯合起來召開了一場會議,決定在其中K棵樹上建造樹洞。
當危險來臨時,每隻兔子均會同時前往距離它最近的樹洞躲避,路程中花費的時間在數值上等於距離。
爲了在最短的時間內讓全部兔子脫離危險,請你安排一種建造樹洞的方式,使最後一隻到達樹洞的兔子所花費的時間儘可能少。

輸入格式

第一行有3個整數N,M,K,分別表示樹(兔子)的個數、路徑數、計劃建造的樹洞數。
接下來M行每行三個整數x,y,表示第x棵樹和第y棵樹之間有一條路徑相連。1<=x,y<=N,x≠y,任意兩棵樹之間至多隻有1條路徑。

輸出格式

一個整數,表示在最優方案下,最後一隻到達樹洞的兔子所花費的時間。

思路:

一眼看出是一道樹上二分

發現只剩下30分鐘了,來不及寫

因而50pts暴力走人

怎麼二分呢?

咱們知道他有k個樹洞

咱們就能夠枚舉長度

判斷此時是否成當即可

相關文章
相關標籤/搜索