其实,这道题本质实在不难,一眼可以看出dp相关,不过细节比较多。
f[i][j]表示,在i,j的最少点击数。
首先,考虑上升的情况,每次可以升随意次,那么f[i][j]=min(f[i][j-k*X[i]]+K)了,但是我们显然要去掉k,就可以采用完全背包的思路。
f[i][j]=min(f[i-1][j-X[i]],f[i][j-X[i]])+1,就好了。
下降没什么好说的,就一个0/1背包,注意柱子的范围。。
还有一点是到达顶端的,这个我们特殊处理一下,减k*X[i]就好了。
最后就是判断答案的过程了。
#include<bits/stdc++.h>
#define N 1000
using namespace std;
int n,m,k,x;
int X[N*10+5],Y[N*10+5],A[N*10+5][2],f[N*10+5][N+5],c[N+5];
int ans;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
int x=0,b=1;
char c=nc();
for(;!(c<='9'&&c>='0');c=nc())if(c=='-')b=-1;
for(;c<='9'&&c>='0';c=nc())x=x*10+c-'0';
return x*b;
}
int main()
{
freopen("in.txt","r",stdin);
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++)X[i]=read(),Y[i]=read(),A[i][0]=1,A[i][1]=m;
for(int i=1;i<=k;i++)
{
x=read(),c[i]=x;
A[x][0]=read(),A[x][1]=read();
A[x][0]++,A[x][1]--;
}
memset(f,37,sizeof(f));
for(int i=1;i<=m;i++)f[0][i]=0;
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],min(f[i-1][j-X[i]],f[i][j-X[i]])+1);
for(int j=0;j<=X[i];j++)f[i][m]=min(f[i][m],min(f[i-1][m-j],f[i][m-j])+1);
for(int j=1;j<=m;j++)
if(A[i][0]<=j&&j<=A[i][1])
if(j+Y[i]<=m)f[i][j]=min(f[i][j],f[i-1][j+Y[i]]);else;
else f[i][j]=1e9;
}
ans=1e9;
for(int i=1;i<=m;i++)ans=min(ans,f[n][i]);
if(ans<1e6)return cout<<1<<endl<<ans,0;
for(int i=1;i<=n;i++)
{
ans=1e9;
for(int j=1;j<=m;j++)ans=min(ans,f[i][j]);
if(ans>=1e6)
{
ans=0;
for(int j=1;j<=k;j++)if(c[j]<i)ans++;
return cout<<0<<endl<<ans,0;
}
}
return 0;
}