题意: 给定每一个外星人的出生时间和消失时间和他和你的距离,为了消灭完他们!我们需要用一个很NB的武器,就是一个什么可以攻击一个圆的武器(以自己为圆心),每次消耗的能量为攻击半径,问我们消灭所有外星人消耗的最小的能量。
>> face <<
Strategy:区间dp 或者记忆化搜索(先离散化一下时间, 毕竟1e4, 而外星人口总共才300多)
状态: d p [ l ] [ r ] → dp[l][r]\to dp[l][r]→该时间区间内的最少花费
目标: m a x ( d p [ 1 ] [ m ] ) max(dp[1][m]) max(dp[1][m]) m是离散化之后的最大的时间;
边界: 本题无
合法判断: 当且仅当在某区间[l, r]内: 存在某外星人从生存到死亡的一个周期, 才能更新答案
转移策略: 若区间[l, r]之内存在外星人(而且是距离我们最远的外星人)$q \in [l_1, r_1] \quad 那么我们可以选择在外星人生存周期的任意时刻发动致命武器 $
转移方程: 以长度为阶段划分, 进行区间dp, 枚举未知, 让所有能转移到该未知的状态来转移
d p [ l ] [ r ] = m i n ( d p [ l ] [ r ] , d p [ l ] [ k ] + d p [ k + 1 ] [ r ] + q [ i d ] . d i s t ) k ∈ [ q [ i d ] . l , q [ i d ] . r ] dp[l][r] = min(dp[l][r], dp[l][k] + dp[k+1][r] + q[id].dist) \quad k \in[q[id].l, q[id].r] dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+q[id].dist)k∈[q[id].l,q[id].r]
attention: 本题是有条件才能转移的dp 只有在该区间内由外星人存在我们才能更新答案, 比如说外星人 q ∈ [ 1 , 5 ] q\in[1, 5] q∈[1,5] 而dp[2][3]应该是多少? 其实是0, 因为你只需要活下来, 并不需要杀灭所有的外星人
双倍经验: 其实只要想到了转移的方式, 无论是区间dp还是记忆化搜索都好写得很, 只不过从效率上来讲, 区间dp还是要快一点的, 毕竟,记忆化超时了
@author jasonleft 区间dp
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define _rep(i, q, b) for (int i = (q); i <= (b); ++i)
#define _rev(i, q, b) for (int i = (q); i >= (b); --i)
#define _for(i, q, b) for (int i = (q); i < (b); ++i)
#define _rof(i, q, b) for (int i = (q); i > (b); --i)
#define ll long long
#define db double
#define oo 0x3f3f3f3f
#define eps 0.00001
#define all(x) x.begin(), x.end()
#define met(q, b) memset(q, b, sizeof(q))
#define what_is(x) cerr << #x << " is " << x << endl
#define lowbit(x) x &(-x)
using namespace std;
const int maxn = 1e3 + 9;
const int mod = 19650827;
struct alians
{
int l, dist, r;
bool operator<(const alians q) const
{
return l < q.l;
}
};
deque<alians> q;
int n, m, dp[maxn][maxn], tim[maxn];
int main()
{
ios::sync_with_stdio(0);
int t;
cin >> t;
while (t--)
{
cin >> n;
_rep(i, 1, n)
{
alians tmp;
cin >> tmp.l >> tmp.r >> tmp.dist;
tim[i] = tmp.l, tim[i + n] = tmp.r;
q.push_back(tmp);
}
sort(tim + 1, tim + 2 * n + 1);
int cnt = (int)(unique(tim + 1, tim + 2 * n + 1) - tim - 1);
_for(i, 0, n)
{
q[i].l = (int)(upper_bound(tim + 1, tim + 1 + cnt, q[i].l) - tim - 1);
q[i].r = (int)(upper_bound(tim + 1, tim + 1 + cnt, q[i].r) - tim - 1);
}
q.push_front((alians){0, 0, 0});
sort(all(q));
_rep(len, 1, cnt)
{
_rep(l, 1, cnt - len + 1)
{
int r = l + len - 1, id = 0;
_rep(i, 1, n) //找被[l, r]包含的最远的外星人
{
if (q[i].l >= l && q[i].r <= r && q[i].dist >= q[id].dist)
{
id = i;
}
}
if (!id)
continue;
dp[l][r] = oo;
_rep(k, q[id].l, q[id].r){
dp[l][r] = min(dp[l][r], dp[l][k-1] + q[id].dist + dp[k+1][r]);
}
}
}
cout << dp[1][cnt] << endl;
met(dp,0), q.clear();
}
}
@author jasonleft 记忆化搜索
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define _rep(i, q, b) for (int i = (q); i <= (b); ++i)
#define _rev(i, q, b) for (int i = (q); i >= (b); --i)
#define _for(i, q, b) for (int i = (q); i < (b); ++i)
#define _rof(i, q, b) for (int i = (q); i > (b); --i)
#define ll long long
#define db double
#define oo 0x3f3f3f3f
#define eps 0.00001
#define all(x) x.begin(), x.end()
#define met(q, b) memset(q, b, sizeof(q))
#define what_is(x) cerr << #x << " is " << x << endl
#define lowbit(x) x &(-x)
using namespace std;
const int maxn = 1e3 + 9;
const int mod = 19650827;
struct alians
{
int l, dist, r;
bool operator<(const alians q) const
{
return l < q.l;
}
};
deque<alians> q;
int n, m, dp[maxn][maxn], tim[maxn];
int dfs(int l, int r)
{
if (l > r)
return 0;
if (dp[l][r])
return dp[l][r];
int id = 0;
_rep(i, 1, n)
{
if (l <= q[i].l && r >= q[i].r && q[id].dist <= q[i].dist)
id = i;
}
if (!id)
return dp[l][r] = 0;
dp[l][r] = oo;
_rep(k, q[id].l, q[id].r)
{
dp[l][r] = min(dp[l][r], dfs(l, k - 1) + q[id].dist + dfs(k + 1, r));
}
return dp[l][r];
}
int main()
{
ios::sync_with_stdio(0);
int t;
cin >> t;
while (t--)
{
cin >> n;
_rep(i, 1, n)
{
alians tmp;
cin >> tmp.l >> tmp.r >> tmp.dist;
tim[i] = tmp.l, tim[i + n] = tmp.r;
q.push_back(tmp);
}
sort(tim + 1, tim + 2 * n + 1);
int cnt = (int)(unique(tim + 1, tim + 2 * n + 1) - tim - 1);
_for(i, 0, n)
{
q[i].l = (int)(upper_bound(tim + 1, tim + 1 + cnt, q[i].l) - tim - 1);
q[i].r = (int)(upper_bound(tim + 1, tim + 1 + cnt, q[i].r) - tim - 1);
}
q.push_front((alians){0, 0, 0});
sort(all(q));
cout << dfs(1, cnt) << endl;
met(dp, 0), q.clear();
}
}
第一次回顾:
- 也许是回顾的太频繁了, 怎么做我都记得
/*
* I Love Coding!
*
* .::::.
* .::::::::.
* :::::::::::
* ..:::::::::::'
* '::::::::::::'
* .::::::::::
* '::::::::::::::..
* ..::::::::::::.
* ``::::::::::::::::
* ::::``:::::::::' .:::.
* ::::' ':::::' .::::::::.
* .::::' :::: .:::::::'::::.
* .:::' ::::: .:::::::::' ':::::.
* .::' :::::.:::::::::' ':::::.
* .::' ::::::::::::::' ``::::.
* ...::: ::::::::::::' ``::.
* ````':. ':::::::::' ::::..
* '.:::::' ':'````..
*/
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (int i = (a); i >= (b); --i)
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rof(i, a, b) for (int i = (a); i > (b); --i)
#define ll long long
#define db double
#define oo 0x3f3f3f3f
#define eps 0.00001
#define all(x) x.begin(), x.end()
#define met(a, b) memset(a, b, sizeof(a))
#define id(x) ((x + 8))
#define what_is(x) cerr << #x << " is " << x << endl
#define lowbit(x) x &(-x)
const int maxn = 9e2 + 9;
const int mod = 19650827;
using namespace std;
ll n, dp[maxn][maxn], tp[maxn * 2];
struct alians
{
int l, r, d;
};
deque<alians> q;
int main()
{
ios::sync_with_stdio(0);
int t;
cin >> t;
while (t--)
{
q.clear();
met(dp, 0);
int n;
cin >> n;
_rep(i, 1, n)
{
alians tmp;
cin >> tmp.l >> tmp.r >> tmp.d;
q.push_back(tmp);
tp[i] = tmp.l, tp[i + n] = tmp.r;
}
sort(tp + 1, tp + n * 2 + 1);
int cnt = unique(tp + 1, tp + 2 * n + 1) - tp - 1;
q.push_front((alians){0, 0, 0});
_rep(i, 1, n)
{
q[i].l = (int)(upper_bound(tp + 1, tp + 1 + cnt, q[i].l) - (tp + 1));
q[i].r = (int)(upper_bound(tp + 1, tp + 1 + cnt, q[i].r) - (tp + 1));
}
_rep(len, 2, cnt)
{
_rep(l, 1, cnt - len + 1)
{
int r = l + len - 1;
int id = 0;
_rep(i, 1, n)
{
if (q[i].l >= l && q[i].r <= r && q[i].d > q[id].d)
id = i;
}
if (!id)
continue;
dp[l][r] = oo;
_rep(k, q[id].l, q[id].r)
{
dp[l][r] = min(dp[l][k - 1] + dp[k + 1][r] + q[id].d, dp[l][r]);
}
}
}
cout << dp[1][cnt] << endl;
}
}