1. 程式人生 > >飛揚的小鳥(NOIP2014)(喪病DP題)

飛揚的小鳥(NOIP2014)(喪病DP題)

發現 iostream pro blog bre nbsp name 小鳥 php

原題傳送門

剛開始我還以為這道題目非常的簡單。。

然後隨便打了一個DP,直接WA,被zxyer狠狠地D了一頓。

然後發現有好多細節。。

首先假如某橫坐標沒有管子,那麽l[x]=0;h[x]=m+1;

然後DP的時候往上是完全背包,往下是01背包。

由於不能接觸到管子,所以0~l[x]和h[x]~m要設值inf方便下面判斷。

m-max(q)*x[i]~m也要特判,因為有限高。。

最後統計答案也是很醉、。、

下面貼代碼。。

#include<iostream> 
#include<cstdio> 
#include<cstdlib> 
#include<cstring> 
#include
<algorithm> #define inf ((1<<31)-2) using namespace std; int f[10001][1001]; int n,m,k,ans; int x[10001],y[10001]; int l[10001],h[10001]; int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]); for(int i=1;i<=n;i++) l[i]
=0,h[i]=m+1; for(int i=1;i<=k;i++) { int p1,l1,h1; scanf("%d%d%d",&p1,&l1,&h1); l[p1]=l1;h[p1]=h1; } for(int i=1;i<=n;i++) for(int j=0;j<=m;j++)f[i][j]=inf; f[0][0]=inf; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) {
if(j>=x[i-1]) { f[i][j]=min(f[i][j],f[i-1][j-x[i-1]]+1); f[i][j]=min(f[i][j],f[i][j-x[i-1]]+1); } if(j==m) { for(int k=j-x[i-1];k<=m;k++) { f[i][j]=min(f[i][j],f[i-1][k]+1); f[i][j]=min(f[i][j],f[i][k]+1); } } } for(int j=l[i]+1;j<h[i];j++) if(j+y[i-1]<=m) f[i][j]=min(f[i][j],f[i-1][j+y[i-1]]); for(int j=1;j<=l[i];j++) f[i][j]=inf; for(int j=h[i];j<=m;j++) f[i][j]=inf; } int cnt=k,ans=inf; for(int i=n;i>=1;i--) { for(int j=l[i]+1;j<h[i];j++) if(f[i][j]<inf) ans=min(ans,f[i][j]); if(ans!=inf)break; if(h[i]<=m)cnt--; } if(cnt==k) printf("1\n%d\n",ans); else printf("0\n%d\n",cnt); return 0; }

飛揚的小鳥(NOIP2014)(喪病DP題)