DP(区间进阶一)

题意: 给定每一个外星人的出生时间和消失时间和他和你的距离,为了消灭完他们!我们需要用一个很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;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值