Codeforces Round #600 (Div. 2) E. Antenna Coverage

Codeforces Round #600 (Div. 2) E. Antenna Coverage(dp)

题目链接

题意:

m只蚂蚁,每只蚂蚁的位置是\(x_i\),分数是\(s_i\),覆盖范围是\([x_i - s_i; x_i + s_i]\),每个硬币可以使一直蚂蚁的\(s_i\)+1,求覆盖整个\([1;m]\)的最少硬币

思路:

\(f[pos][0]\)表示\([1,pos]\)没有被覆盖还要花费的最少硬币,\(f[pos][1]\)表示\([1,pos]\)被覆盖的最小花费硬币,对于每个\(pos\)枚举蚂蚁,有以下这几种情况

  • \(pos\)在\(x_i\)的右边,且蚂蚁\(i\)扩展到\(pos\)时的左边已经有蚂蚁覆盖,则蚂蚁\(i\)扩展到\(pos\)时\(f[pos][1] = min(f[pos][1],f[max(2*x[j]-pos-1,0)][1]+max(pos-x[j]-s[j],0));\)
  • \(pos\)在\(x_i\)的右边,且蚂蚁\(i\)扩展到\(pos\)时的左边无蚂蚁覆盖,则蚂蚁\(i\)扩展到\(pos\)时\(f[pos][1] = min(f[pos][1],f[max(2*x[j]-pos-1,0)][0]+1+max(pos-x[j]-s[j],0));\)
  • \(pos\)在\(x_i\)的左边,则只需扩展\(x_i\)的左侧\(f[pos][1] = min(f[pos][1],min(f[max(x[j]-s[j]-1,0)][1],f[max(x[j]-s[j],0)][0]));\)

    \(f[i][1]\)和\(f[i][0]\)的区别是若左边已经有蚂蚁覆盖了,就可以少去覆盖\([i-1,i]\)的花费

    代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 200100;
int f[N][2],s[N],x[N];
int main()
{
    int n,m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) f[i][0]=i-1,f[i][1]=1<<30;
    f[0][1] = 0;
    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])
     {
        f[i][1] = min(f[i][1],f[max(2*x[j]-i-1,0)][1]+max(i-x[j]-s[j],0));
        f[i][1] = min(f[i][1],f[max(2*x[j]-i-1,0)][0]+1+max(i-x[j]-s[j],0));
     }
     else
     {
       f[i][1] = min(f[i][1],f[max(x[j]-s[j]-1,0)][1]);
       f[i][1] = min(f[i][1],f[max(x[j]-s[j],0)][0]);
     }
    cout << f[m][1] << endl;
} 

原文地址:https://www.cnblogs.com/7osen/p/11875441.html

时间: 2024-08-09 11:11:36

Codeforces Round #600 (Div. 2) E. Antenna Coverage的相关文章

【题解】Codeforces Round #600(Div.2)

Codeforces Round #600(Div.2) https://codeforces.com/contest/1253/problem A.Single Push 思路:数组各位相减,得到b-a之后的.如果全为0,或者只有一段非0且数字相同则可行,否则不可行.具体实现的话,可以左右两边指针向中间搜到第一个不为0的数,再判断中间是否均为同一个数.复杂度\(O(n)\). 注意:多组数据一定要判断是否需要清空.这里我a[n+1]没有清0,结果WA on test55-- AC代码: #in

【cf比赛记录】Codeforces Round #600 (Div. 2)

Codeforces Round #600 (Div. 2) ---- 比赛传送门 昨晚成绩还好,AC A,B题,还能上分(到底有多菜) 补了C.D题,因为昨晚对C.D题已经有想法了,所以补起题来也快.(C题TLE了,D题想用并查集没好) A // http://codeforces.com/contest/1253/problem/A /* 如果YES,则b[i] - a[i] 在一个区间里的差肯定是相同的且不小于0 */ #include<iostream> #include<cst

Codeforces Round #600 (Div. 2)

A - Single Push 题意:给数组a和数组b,可以选择一段连续的区间[l,r]使得ai全部加k(k>0)至多一次.求能不能从a变成b. 题解:一开始作差排序去重,然后判断差是不是只有1个(且>=0)或只有两个(且c1=0,c2>0),但这样是错的,比如下面的样例. 1 5 1 1 1 1 1 2 1 2 2 2 因为虽然差都是1但不是连续的区间. 做法是作差,然后判断是否有至多一个正的方波.可以用两个变量,一个记录是否进入了方波,且方波的高是多少.另一个记录是否离开了方波. #

第五天打卡 Codeforces Round #600 (Div. 2)

A题: #include<bits/stdc++.h> using namespace std; #define ll long long const int N = 1e5+10; int a[N],b[N]; int main(){ int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); int need = -9999999; bool ok = true; for(in

Codeforces Round #535 (Div. 3) 题解

Codeforces Round #535 (Div. 3) 题目总链接:https://codeforces.com/contest/1108 太懒了啊~好久之前的我现在才更新,赶紧补上吧,不能漏掉了. A. Two distinct points 题意: 给出两个区间的左右边界,输出两个数,满足两个数分别在两个区间内且这两个数不相等. 题解: 直接输出左端点然后判断一下就行了. 代码如下: #include <bits/stdc++.h> using namespace std; type

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd