这是一道很好的dp题。
30分的搜索;
70分的裸dp;
100分的复杂度压缩。
需要注意的问题是H数组要初始化。我的代码一开始在没有到达终点而且没有飞过一颗柱子时是没有输出的,一开始在luogu,vijos上都过了,在uoj上检查出了这个小bug,已改。
看了了这位大佬的博客,在此表示感谢和膜拜。
30分
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<queue>
#define LL long long
using namespace std;
const int N=10009;
const int inf=2e9;
int n,m,k;
int X[N],Y[N];
int H[N],L[N];
bool e[N];
int ans=inf;
void dfs(int h,int x,int step)
{
if(x==n+1)
{
ans=min(ans,step);
return;
}
if(h<=0) return;
if(e[x]&&(h<=L[x]||h>=H[x])) return;
for(int i=1;i<=3;i++)
{
dfs(min(h+i*X[x],m),x+1,step+i);
}
dfs(h-Y[x],x+1,step);
}
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<=k;i++)
{
int p,l,h;
scanf("%d%d%d",&p,&l,&h);
H[p]=h,L[p]=l;e[p]=1;
}
for(int i=1;i<=m;i++) dfs(i,0,0);
if(ans!=inf) printf("1\n%d",ans);
else printf("0%d\n",5);
return 0;
}
70分
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<queue>
#define LL long long
using namespace std;
const int N=10009;
const int M=1009;
int n,m,k;
int X[N],Y[N];
int H[N],L[N];
int e[N];
int f[N][M],ans;
int main()
{
memset(f,127/3,sizeof(f));
memset(L,0,sizeof(L));
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<=n;i++) H[i]=m+1;
for(int i=0;i<n;i++) scanf("%d%d",&X[i],&Y[i]);
for(int i=1;i<=k;i++)
{
int p,l,h;
scanf("%d%d%d",&p,&l,&h);
H[p]=h,L[p]=l;e[p]=1;
}
for(int i=1;i<=n;i++) e[i]+=e[i-1];
for(int i=1;i<=m;i++) f[0][i]=0;
for(int i=1;i<=n;i++)
{
for(int j=L[i]+1;j<H[i];j++)
{
for(int p=1;j-p*X[i-1]>0;p++)
if(j-p*X[i-1]>L[i-1]&&j-p*X[i-1]<H[i-1])
f[i][j]=min(f[i][j],f[i-1][j-p*X[i-1]]+p);
if(j+Y[i-1]<H[i-1]&&j+Y[i-1]>L[i-1])f[i][j]=min(f[i][j],f[i-1][j+Y[i-1]]);
if(j==m)
for(int p=L[i-1]+1;p<H[i-1];p++)
f[i][j]=min(f[i][j],f[i-1][p]+(j-p)/X[i-1]+1);
}
}
ans=f[0][0];
for(int i=1;i<=m;i++) ans=min(ans,f[n][i]);
if(ans!=f[0][0]) printf("1\n%d",ans);
else
{
for(int i=n;i>=1;i--)
for(int j=1;j<=m;j++)
{
if(f[i][j]!=f[0][0])
{
printf("0\n%d",e[i]);
return 0;
}
}
}
return 0;
}
100分
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<queue>
#define LL long long
using namespace std;
const int N=10009;
const int M=1009;
int n,m,k;
int X[N],Y[N];
int H[N],L[N];
int e[N];
int f[N][M],ans;
int main()
{
memset(f,127/3,sizeof(f));
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<=n;i++) H[i]=m+1;
for(int i=0;i<n;i++) scanf("%d%d",&X[i],&Y[i]);
for(int i=1;i<=k;i++)
{
int p,l,h;
scanf("%d%d%d",&p,&l,&h);
H[p]=h,L[p]=l;e[p]=1;
}
for(int i=1;i<=n;i++) e[i]+=e[i-1];
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]>0) f[i][j]=f[i][j-X[i-1]]+1;//优化
if(j-X[i-1]>L[i-1]&&j-X[i-1]<H[i-1])
f[i][j]=min(f[i][j],f[i-1][j-X[i-1]]+1);
if(j==m)
{
for(int p=L[i-1]+1;p<H[i-1];p++)
f[i][j]=min(f[i][j],f[i-1][p]+(j-p)/X[i-1]+1);
}
}
for(int j=L[i]+1;j<H[i];j++)
if(j+Y[i-1]<H[i-1]&&j+Y[i-1]>L[i-1]) f[i][j]=min(f[i-1][j+Y[i-1]],f[i][j]);
}
ans=f[0][0];
for(int i=1;i<=m;i++) ans=min(ans,f[n][i]);
if(ans!=f[0][0]) {printf("1\n%d",ans);return 0;}
else
{
for(int i=n;i>=1;i--)
for(int j=L[i]+1;j<H[i];j++)
{
if(f[i][j]<f[0][0])
{
printf("0\n%d",e[i]);
return 0;
}
}
}
printf("0\n0");
return 0;
}