刚开始我还以为这道题目非常的简单。。
然后随便打了一个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; }
时间: 2024-10-12 01:03:40