有区间限制的树形DP
开始以为等级限制为M时,只要等级和酋长的等级之差在小于等于M即可,实际上这是错的,因为可能有人的等级高于酋长,这些人和低于酋长的人的等级差可能大于M。
因此想到了枚举区间,然后在DP时只考虑在选定区间中的物品。
枚举区间的方法是先枚举区间长度,在枚举区间起点。
代码:
//
// main.cpp
// 1062 昂贵的聘礼
//
// Created by Baoli1100 on 15/4/7.
// Copyright (c) 2015年 Baoli1100. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
#define INF 100000000
int M,N;
int d[105];
vector<int> G[105];
vector<int> P[105];
int p[105];
int l[105];
int sl,tl;
int dp(int n){
if(d[n]) return d[n];
d[n]=p[n];
for(int i=0;i<G[n].size();i++){
int cur=G[n][i];
if(l[cur]<=tl&&l[cur]>=sl){
int k=min(p[cur],dp(cur));
d[n]=min(d[n],k+P[n][i]);
}
}
return d[n];
}
int main(){
scanf("%d%d",&M,&N);
int bl=0,al=INF;
for(int i=1;i<=N;i++){
G[i].clear();
P[i].clear();
int n;
scanf("%d%d%d",&p[i],&l[i],&n);
bl=max(bl,l[i]);
al=min(al,l[i]);
for(int j=0;j<n;j++){
int t,k;
scanf("%d%d",&t,&k);
G[i].push_back(t);
P[i].push_back(k);
}
}
int res=INF;
for(int i=0;i<=M;i++){
for(int j=al;j<=bl-i;j++){
if(j>l[1]||j+i<l[1]) continue;
memset(d,0,sizeof(d));
sl=j;tl=j+i;
res=min(res,dp(1));
}
}
printf("%d\n",res);
}