2015湖南省赛A题 BZOJ4254 Aerial Tramway 树形dp

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=4254

题意:按照规则选m条线段,使得不超过k限制,得到权值和最大。

题解:按照给定的规则,一条合法的线段下面必须全部低于此线段,也就是每一个线段一定被某个线段的完全覆盖,且不会出现线段非重合相交的情况。故所有的线段依据覆盖关系可形成一个森林,创建虚拟节点0,使得构建一棵树。然后就是树形dp,dfs过程中要套一个背包。其实最重要的是转换出这个模型。

   f[i][d][j] 表示在i节点选取d个线段,重叠最大次数不超过j的最优方案。转移过程就是对i的儿子背包,注意要做两次背包,一次是不选i这个线段,另一个是必须选i。

代码:

#include
#include
#include
#include
#include
using namespace std;
const int N = 510;
const int inf = 1e8;
typedef long long ll;
int f[N][N][15],val[N];
struct point{
    int x,y;
}p[N];
int cmp1(point a,point b){
    return a.x < b.x;
}
struct line{
    int x1,x2,y;
    line(){}
    line(int _x1,int _x2,int _y){
        x1 = _x1; x2 = _x2; y = _y;
    }
}le[N];
int cmp2(line a,line b){
    return abs(a.x2-a.x1) < abs(b.x2-b.x1);
}
int n,m,k,num;
vector g[N];
vector son[N];
void make_line(){
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
            if(p[i].y==p[j].y){
                int flag = 1;
                for(int d=i+1;d=p[i].y) flag=0;
                if(!flag) continue;
                le[++num] = line(p[i].x,p[j].x,p[i].y);
                break;
            }
        }
}
void tro_line(){
    for(int i=1;i<=num;i++){
        int flag = 1;
        for(int j=i+1;j<=num;j++)if(le[i].y < le[j].y){
            if(le[i].x1>le[j].x1 && le[i].x20?f[0][m][k-1]:-1) );
    }
    return 0;
}


你可能感兴趣的:(DP)