E. Antenna Coverage(Codeforces Round #600 (Div. 2))(dp-贪心)
The meaning of problems
Have antennas, each antenna has a certain radius may cover a certain area on the number line. Now you can perform an action to make a coverage radius of the antenna increases , you can perform any number of times such an operation.
Now ask how many times you can perform a minimum cover from in all regions?
answer
Please be understood in conjunction with code comments
Code
#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;
}
Another approach
Dfs search through memory, except that this is pushed backwards, and above that is a positive push.
Code
#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);
}