E. 안테나 범위 (Codeforces 라운드 # 600 (사업부. 2)) (dp- 贪心)

E. 안테나 범위 (Codeforces 라운드 # 600 (사업부. 2)) (dp- 贪心)

그림 삽입 설명 여기

문제의 의미

되세요 개의 안테나가 각각의 안테나는 다수의 라인의 특정 영역을 커버 할 수있는 소정의 반경을 갖는다. 지금 당신은 안테나 증가 커버리지 반경을 만들기 위해 작업을 수행 할 수 있습니다 1 1 , 당신은 여러 번에게 이러한 작업을 수행 할 수 있습니다.

이제부터 최소 커버를 수행 할 수있는 횟수를 물어 1 - 미디엄 1-m 지역에서는?

문제 해결

코드 주석과 함께 이해하시기 바랍니다

그림 삽입 설명 여기

코드

#include<bits/stdc++.h>
#define maxn 200010
using namespace std;

int n, m, dp[maxn], s[maxn], x[maxn];	//dp[i]表示覆盖到i位置所需的最小花费
int main() {
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
		dp[i] = i;
	for (int i = 1; i <= n; i++)
		cin >> x[i] >> s[i];
	for (int i = 1; i <= m; i++)
		for (int j = 1; j <= n; j++) {
			if (i >= x[j])
				dp[i] = min(dp[i], dp[max(2 * x[j] - i - 1, 0)]/*覆盖到左边缘所需的最小花费*/ + max(i - x[j] - s[j], 0)/*从右边缘覆盖到i所需的花费*/);
			else
				dp[i] = min(dp[i], dp[max(x[j] - s[j] - 1, 0)]);	//
		}
	cout << dp[m] << endl;
	return 0;
}

또 다른 방법

DFS는이 뒤로 밀려 것을 제외하고, 메모리를 검색하고, 그 위에 포지티브 푸시된다.

코드

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define sec second
typedef int ll;
typedef long double  ld;
#define pii pair<ll,ll> 
#define fast ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mem(a,b) memset(a,b,sizeof(a))
ll dp[2][80][100001];	//dp[i][j][k]表示第j个天线用过(i = 1)/没用过(i = 0)时从k覆盖到m的最小花费
ll n, m;
pii arr[100];
ll func(ll pehlibaar, ll index, ll reach) {
	if (reach > m) return 0;	//如果已经覆盖到了m,就不需再额外覆盖
	if (index == n) return 1e7;
	ll &ret = dp[pehlibaar][index][reach];
	if (ret != -1) return ret;	//记忆化搜索
	ret = func(0, index + 1, reach);	//优先考虑后面的天线,得出后面的天线后的最优结果后记录数据,然后用之前得出过的最优结果
	if (pehlibaar == 0) {	//如果当前天线还没用过
		ll x = arr[index].fi - arr[index].sec;	//第index个天线的覆盖下限
		if (x >= reach) {	//如果当前要覆盖的位置在第index个天线的下限之前,说明当前要覆盖的位置离index天线之间该有距离离,需要加上这部分距离,即(x - reach)
			ret = min(ret, func(1, index, arr[index].fi + arr[index].sec + x - reach + 1) + x - reach);
		}
		else if (reach <= arr[index].fi + arr[index].sec) {	//如果当前要覆盖的位置正好在第index天线的下限上或者在其之后,则不需要不上中间的距离,只需要加上这个天线覆盖的最小花费
			ret = min(ret, func(1, index, arr[index].fi + arr[index].sec + 1));	//1表示第index已经用过了,只需要把reach往后推即可
		}
	}
	else {	//如果当前天线已经用过了,那么就把天线扩大一下继续用
		ret = min(ret, func(1, index, reach + 1) + 1);
	}
	return ret;
}
signed main() {
	freopen("in.txt", "r", stdin);
	fast;
	cin >> n >> m;
	ll i;
	for (i = 0; i < n; i++)
		cin >> arr[i].fi >> arr[i].sec;
	sort(arr, arr + n);
	mem(dp, -1);
	cout << func(0, 0, 1);
}
게시 된 163 개 원래 기사 · 원의 찬양 (54) ·은 30000 +를 볼

추천

출처blog.csdn.net/weixin_42856843/article/details/103115265