cf 1106e dp
题意: 父亲在时间流水(n 1e5)上选择东西(k 1e5),每个有它的价值w和可被选择起止时间s,t,在选择之后以及到时间d,不可再选,父亲有固有的选择策略。
但是女儿可以打断父亲m(200)次,使其不能选择,求最后的最小值是多少
思路:dp 假设不存在打断的情况,那么父亲就按照一个固有的顺序选择了。d[i][j] 表示在打断i次 ,走到 j 可以获得最小值。
按照时间的顺序, i可能打断那么就是 d[i+1[j+1]的时候,不打断,父亲按照固有策略去选择。
值得学习的地方是,利用map的排序来 以及它的erase 和insert来表示了在时间i的选择的可能和最佳情况
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define fi first #define se second #define all(v) v.begin(),v.end() #define mem(a) memset(a,0,sizeof(a)) const int M = 202; const int N = 1e5+4; const ll mod =1e9+7; const ll INF = 1e18+4; const double eps = 1e-7; struct node{ int d,w; //题目要求的父亲的选择策略 friend bool operator <(node a,node b){ return a.w>b.w || (a.w==b.w && a.d>b.d ); } }; map<node,int>choice; vector<node>V[N],T[N]; node a[N]; ll d[M][N]; void insert(node x){ if(choice.count(x)) choice[x]++; else choice[x]=1; } void erase(node x){ choice[x]--; if(choice[x]==0) choice.erase(x); } int main(){ int n,m,k; cin>>n>>m>>k; for(int i=0;i<k;++i){ int s,t,d,w; cin>>s>>t>>d>>w; V[s].pb(node{d,w}); T[t+1].pb(node{d,w}); } for(int i=1;i<=n;++i){ for(int j=0;j<V[i].size();++j) insert(V[i][j]); for(int j=0;j<T[i].size();++j) erase(T[i][j]); //这是父亲要选择的最佳 if(choice.size()){ a[i]= (*choice.begin()).first; } else a[i] =node{i,0}; } for(int i=0;i<=m;++i) for(int j=0;j<=n+111;++j) d[i][j]=INF; ll ans =INF; d[0][1]=0; for(int j=0;j<=m;++j){ for(int i=1;i<=n;++i){ //假设在i时间打断 d[j+1][i+1] = min(d[j+1][i+1],d[j][i]); //不打断,则父亲选择a[i] 之后的min是因为可能还有其他选择方法导致的可能 d[j][a[i].d+1] = min(d[j][a[i].d+1],d[j][i]+a[i].w); } ans = min(ans,d[j][n+1]); } cout<<ans<<endl; return 0; }