标签:线段 show multi ++ 区间dp int include 其他 bool
http://acm.hdu.edu.cn/showproblem.php?pid=6365
定义dp[i][j]为穿过包含在(i,j)区间所有直线所需要的最小代价(即穿过(i,j)区间但并不在i,j区间内的直线可能会被穿过,但是贡献在之前已经被计算了)
转移方程为
dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+w[k]);
#include<bits/stdc++.h>
#define M 305
#define ll long long
#define inf 1e16
using namespace std;
int n,i,T,sz;
ll h[M<<1],w[M<<1],l[M<<1],r[M<<1],dp[M<<1][M<<1];
struct N{
ll x,y;
N(){}
N(ll x,ll y): x(x),y(y){}
bool operator ==(const N& rhp)const{
return x*rhp.y-y*rhp.x==0;
}
bool operator<(const N& rhp)const{
return x*rhp.y-y*rhp.x<0;
}
}p[M<<1];
int id(N a){ return lower_bound(p+1,p+1+sz,a)-p;}
ll dfs(int L,int R){
ll &ans=dp[L][R];
if(L>R)return 0;
if(ans!=-1)return ans;
ans=0;
ll ma=-1,x;
for(int i=1;i<=n;i++){
if(L<=l[i]&&r[i]<=R){
if(w[i]>ma){
ma=w[i];x=i;
}
}
}
if(ma==-1)return ans;
ans=inf;
for(int i=l[x];i<=r[x];i++){
ans=min(ans,dfs(L,i-1)+dfs(i+1,R)+ma);
}
return ans;
}
int main(){
scanf("%d",&T);
while(T--){
memset(dp,-1,sizeof(dp));
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lld%lld%lld%lld",&h[i],&l[i],&r[i],&w[i]);
p[2*i-1]=N(l[i],h[i]);
p[2*i]=N(r[i],h[i]);
}
sort(p+1,p+1+2*n);
sz=unique(p+1,p+2*n+1)-p-1;
for(i=1;i<=n;i++){
l[i]=id(N(l[i],h[i]));
r[i]=id(N(r[i],h[i]));
}
printf("%lld\n",dfs(1,sz));
}
}
hdu6365 2018 Multi-University Training Contest 6 1004 Shoot Game
标签:线段 show multi ++ 区间dp int include 其他 bool
原文地址:https://www.cnblogs.com/VIrtu0s0/p/9596046.html