考完以后听说是中期题区间DP?我考场上竟然没去看?然而时隔一周我发现我这题还没有补掉,于是今天乘着没有可做题补来看一蛤,结果就是1个小时毫无思路,根本不知道区间怎么设定,讲道理要按极角排序的,然而因为一条线段有两个点,所以他极角排序的可能是相隔的,那dp[i][j]表示i到j个点被覆盖的最小值?有些线段在i-j中间,有些只有1个点在中间怎么办?于是乎哀我太菜,看波题解,原来题解的表示方法是dp[i][j]表示i到j的极角区间中2个点都在里面的线段被覆盖的条件,那么这个区间中最大的线段是一定加入花费中的,那么就枚举这个线段两个端点的中间的位置,区间最优值合并一蛤,就能表示这个最大线段不摧毁的情况时加上被摧毁的花费
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 666
using namespace std;
int n,tot,cnt;
struct node
{
int x,y,id;bool isl;
node(){}
node(int x,int y,bool isl,int id):x(x),y(y),isl(isl),id(id){};
bool operator != (const node &b) const
{
return 1ll*x*b.y-1ll*b.x*y!=0;
}
bool operator <(const node &b) const
{
return 1ll*b.y*x-1ll*b.x*y<0;
}
}a[maxl];
int l[maxl],r[maxl],w[maxl],h[maxl];
long long f[maxl][maxl];
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&h[i],&l[i],&r[i],&w[i]);
a[i*2-1]=node(l[i],h[i],true,i);
a[i<<1]=node(r[i],h[i],false,i);
}
sort(a+1,a+1+2*n);
cnt=1;
if(a[1].isl)
l[a[1].id]=1;
else
r[a[1].id]=1;
for(int i=2;i<=2*n;i++)
{
if(a[i]!=a[i-1])
cnt++;
if(a[i].isl)
l[a[i].id]=cnt;
else
r[a[i].id]=cnt;
}
}
inline void mainwork()
{
int j;
for(int len=1;len<=cnt;len++)
for(int i=1;i+len-1<=cnt;i++)
{
j=i+len-1;
int mx=-1,mxind;
for(int k=1;k<=n;k++)
if(i<=l[k] && r[k]<=j)
if(w[k]>mx)
mx=w[k],mxind=k;
f[i][j]=1ll<<62;
if(mx==-1)
f[i][j]=0;
else
for(int k=l[mxind];k<=r[mxind];k++)
f[i][j]=min(f[i][j],f[i][k-1]+f[k+1][j]+mx);
}
}
inline void print()
{
printf("%lld\n",f[1][cnt]);
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}