坑到爆炸……
想转移方程+打代码一个中午不到的事,调细节调了将近两个中午…………………………
这道题看上去真的就是P1156的改版啊喂……
首先认真看完这道题肯定会想到下面的这个东西:
f[i][j]=min(f[i][j],min(f[i][j-data[i-1].up],f[i-1][j-data[i-1].up])+1) j>data[i-1].up
=min(f[i][j],f[i-1][j+data[i-1].down]) j+data[i-1].down<=m
然后——如果你发现你少想了这些东西,你很幸运;如果你没发现,打代码时砸键盘吧:
repu(j,m-data[i-1].up,m)
f[i][m]=min(f[i][m],min(f[i][j],f[i-1][j])+1);
repu(j,1,data[i].downbound)
f[i][j]=inf;
repu(j,data[i].upbound,m)
f[i][j]=inf;
(downbound=下界,upbound=上界)
其实就是一个细节多到令人头皮发麻的完全背包(Orz LJ 伪棋盘)
而且即使你把上面的方程都想到了,打代码的时候也还是会想砸键盘……
我才不会说我调循环变量就快调疯了……
上代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define repu(i,l,r) for(int i=l;i<=r;i++)
#define repd(i,r,l) for(int i=r;i>=l;i--)
#define inf 9999973
using namespace std;
struct d
{
int up,down,upbound,downbound;
}data[15000];
int n,m,k,f[15000][1500],pillar[15000],passed;
int read()
{
char ch=getchar();
int p=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9')
{
p=p*10+ch-'0';
ch=getchar();
}
return p;
}
int fail(int end)
{
int ans=0;
repd(i,end-1,0)
ans+=pillar[i];
return ans;
}
int main()
{
n=read();m=read();k=read();
repu(i,0,n-1)
{
data[i].up=read();
data[i].down=read();
data[i].upbound=m+1;
data[i].downbound=0;
}
data[n].upbound=m+1,data[n].downbound=0;
repu(i,1,k)
{
int pos=read();
data[pos].downbound=read();
data[pos].upbound=read();
pillar[pos]=1;
}
repu(i,1,n)
{
repu(j,1,m)
{
f[i][j]=inf;
if (j>data[i-1].up)f[i][j]=min(f[i][j],min(f[i-1][j-data[i-1].up],f[i][j-data[i-1].up])+1);
}
repu(j,m-data[i-1].up,m)
f[i][m]=min(f[i][m],min(f[i][j],f[i-1][j])+1);
repu(j,1,m-data[i-1].down)
f[i][j]=min(f[i][j],f[i-1][j+data[i-1].down]);
repu(j,1,data[i].downbound)
f[i][j]=inf;
repu(j,data[i].upbound,m)
f[i][j]=inf;
passed=0;
repu(j,1,m)
if (f[i][j]<inf)
passed=1;
if (!passed)
{
printf("0\n");
printf("%d\n",fail(i));
return 0;
}
}
int ans=inf;
repu(i,1,m)
ans=min(ans,f[n][i]);
printf("1\n");
printf("%d\n",ans);
return 0;
}