飞扬的小鸟
这一题开始看到时就知道是DP,但作死打了个dfs,只有75分……
//卡常大法好
#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
const int inf = 9999999;
int g_sum[N],g_up[N],g_down[N],up[N],down[N],n,m,k,f[N][1005],ff,p,l,h,ans,anss=inf;
inline void dfs(int x,int y,int o){
if(o>=anss)return;
if(y>m) y=m;
if(y<=0)return;
if(y>=g_up[x]||y<=g_down[x]) return;
if(f[x][y]<=o) return;
f[x][y]=o;
if(x>=n){
ff=1;
anss=min(anss,o);
return;
}
dfs(x+1,y-down[x],o);
for(register int i=1;y+i*up[x]<=m+up[x];i++)
dfs(x+1,y+up[x]*i,o+i);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(register int i=0;i<=n+1;i++)
for(register int j=1;j<=m;j++) f[i][j]=inf;
for(register int i=0;i<=n;i++) g_up[i]=m+1;
for(register int i=0;i<n;i++) scanf("%d%d",&up[i],&down[i]);
for(register int i=1;i<=k;i++){
scanf("%d%d%d",&p,&l,&h);
g_up[p]=h;
g_down[p]=l;
}
for(register int i=1;i<=n;i++){
g_sum[i]=g_sum[i-1];
if(g_up[i]!=m+1||g_down[i]) g_sum[i]++;
}
for(register int i=1;i<=m;i++){
dfs(0,i,0);
}
printf("%d\n",ff);
if(ff){
ans=inf;
for(register int i=1;i<=m;i++) ans=min(ans,f[n][i]);
printf("%d",ans);
}else{
for(register int i=n;i>=1;i--){
for(register int j=1;j<=m;j++){
if(f[i][j]!=inf){
printf("%d",g_sum[i]);
return 0;
}
}
}
}
return 0;
}
"剪枝减去我们的(到我们)疯狂……”
快疯掉了,然后打了一波DP,维护把三重循环优化成了两重,
上吧,我的代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
const int inf = 9999999;
int g_sum[N],g_up[N],g_down[N],up[N],down[N],n,m,k,f[N][1005],ff,p,l,h,ans,anss=inf,fa[N];
void work(){
for(register int i=1;i<=n;i++){
for(register int j=1;j<=m;j++) fa[j]=inf;
int dow=down[i-1];
int u=up[i-1];
for(register int j=1;j<=m;j++){
if(j-u<g_up[i-1]&&j-u>g_down[i-1])fa[j]=min(fa[j],f[i-1][j-u]+1);
if(j+dow<g_up[i-1]&&j+dow>g_down[i-1])f[i][j]=min(f[i][j],f[i-1][j+dow]);
if(j-u<g_up[i-1]&&j-u>g_down[i-1]) f[i][j]=min(f[i][j],f[i-1][j-u]+1);
if(j-u>0)f[i][j]=min(f[i][j],fa[j-u]+1);
if(j-u>0)fa[j]=min(fa[j],fa[j-u]+1);
}
for(register int j=m;j<=m+u;j++){
if(j-u<g_up[i-1]&&j-u>g_down[i-1]) f[i][m]=min(f[i][m],f[i-1][j-u]+1);
if(j-u>0)f[i][m]=min(f[i][m],fa[j-u]+1);
}
}
for(int i=1;i<=m;i++) if(f[n][i]!=inf) ff=1;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(register int i=0;i<=n+1;i++)
for(register int j=1;j<=m;j++) f[i][j]=inf;
for(register int i=0;i<=n;i++) g_up[i]=m+1;
for(register int i=0;i<n;i++) scanf("%d%d",&up[i],&down[i]);
for(register int i=1;i<=k;i++){
scanf("%d%d%d",&p,&l,&h);
g_up[p]=h;
g_down[p]=l;
}
for(register int i=1;i<=n;i++){
g_sum[i]=g_sum[i-1];
if(g_up[i]!=m+1||g_down[i]) g_sum[i]++;
}
for(register int i=1;i<=m;i++) f[0][i]=0;
work();
printf("%d\n",ff);
if(ff){
ans=inf;
for(register int i=1;i<=m;i++) ans=min(ans,f[n][i]);
printf("%d",ans);
}else{
for(register int i=n;i>=1;i--){
for(register int j=1;j<=m;j++){
if(f[i][j]!=inf&&j<g_up[i]&&j>g_down[i]){
printf("%d",g_sum[i]);
return 0;
}
}
}
}
return 0;
}