[P1941] [NOIP2014T3]飛ぶ鳥0/1フルバックパックバックパック+

質問の意味:マップ与えられ、垂直パイプの数があり、鳥が右端をマッピングするために一番左のマップから飛んで、クリックしない場合、鳥は意志、鳥が上昇すると、画面上の各時間をクリックしてください減少;鳥が飛ぶことができない方法(うちは)マップは、パイプラインを満たすことができません。

マップから、右のマップ​​は、彼らができる場合は、クリック数の最小値が数値の場合、この鳥が左に飛ぶことができる見つけます。

ソリューション:0/1 +バックパックフルバックパック。

1.0 / 1バックパック、この位置で(i、j)の中の鳥は、画面上でクリックしなくてもよい場合、0/1、時間はバックパックであり、状態遷移方程式:[I] [J] F =分([F I-1] F [JX [I] + 1、[I] [JX [I] + 1)。

2.完全にバックパック;この位置で(I、j)における鳥は、あなたが画面上で数回クリックすることができ、その後、時間がいっぱいのバックパックで、状態遷移方程式:[i]の[J] =分([F f iを] [J]、[I [J + Y [I-1] F])。

F [I] [J] = INFにダクト場所;から転送は、下から上へ、左から右に、

コードを接続します。

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=10086; const int inf = 0x3f3f3f3f; inline int read(){ int ref=0,x=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')x=-1;ch=getchar();} while(isdigit(ch)){ref=ref*10+ch-'0';ch=getchar();} return ref*x; } int n,m,p; int x[N],y[N]; int low[N],high[N],dp[N][2019]; bool jud[N]; int main() { scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=n;i++) x[i]=read(),y[i]=read(); for(int i=1;i<=n;i++){ low[i]=1; high[i]=m; } for(int i=1;i<=p;i++){ int a,b,c; a=read(),b=read(),c=read(); jud[a]=1; low[a]=b+1; high[a]=c-1; } memset(dp,0x3f3f3f,sizeof(dp)); for(int i=1;i<=m;i++) dp[0][i]=0; for(int i=1;i<=n;i++){ for(int j=x[i]+1;j<=m+x[i];j++) dp[i][j]=min(dp[i-1][j-x[i]]+1,dp[i][j-x[i]]+1); for(int j=1;j<=m-y[i];j++) dp[i][j]=min(dp[i][j],dp[i-1][j+y[i]]); for(int j=m+1;j<=m+x[i];j++) dp[i][m]=min(dp[i][m],dp[i][j]); for(int j=1;j<low[i];j++) dp[i][j]=inf; for(int j=high[i]+1;j<=m;j++) dp[i][j]=inf; } int ans=inf; for(int j=1;j<=m;j++) { ans=min(ans,dp[n][j]); } if(ans<inf) printf("1\n%d",ans); else{ int place; bool ljw=false; for(int i=n-1;i>=1;i--) { for(int j=1;j<=m;j++){ if(dp[i][j]<inf){ place=i; ljw=true; break; } } if(ljw) break; } ans=0; for(int i=1;i<=place;i++){ if(jud[i]) ans++; } printf("0\n%d",ans); } return 0; }

おすすめ

転載: www.cnblogs.com/nnezgy/p/11371895.html