Codeforces 988F Rain and Umbrellas(DP)

题目链接:http://codeforces.com/contest/988/problem/F

题目大意:

有三个整数a,n,m,a是终点坐标,给出n个范围(l,r)表示这块区域下雨,m把伞(p,w)在点p有重量为w的伞。

小明可以携带任意数量的伞,经过下雨处时必须要撑伞,小明每走一个单位长度消耗的体力与他所携带伞的重量相同,

求小明从0~a所需消耗的最少体力,若无解则输出-1。

解题思路:

第一种解法:

设dp[i]表示到达i点所需花费的最少体力,rain[i]表示第i段是否下雨(注意是段不是点),ub[j]表示j点放置的伞的重量。

则当rain[i-1]=false时,dp[i]=dp[i]-1

rain[i-1]=true是,dp[i]=min{dp[j]+(i-j)*ub[j]},(ub[j]!=1e18且j<=i-1)

复杂度O(n^2)

第二种解法:

设dp数组,

dp[i][0]表示到达第i段不拿伞最小花费
dp[i][1]表示到达第i段拿伞最小化费
dp[i][2]表示到达第i段拿最小重量的伞的最小化费

然后不想说了,各种递推就是了。。。

复杂度O(n)

代码:

解法一:

 1 #include<bits/stdc++.h>
 2 #define lc(a) (a<<1)
 3 #define rc(a) (a<<1|1)
 4 #define MID(a,b) ((a+b)>>1)
 5 #define fin(name)  freopen(name,"r",stdin)
 6 #define fout(name) freopen(name,"w",stdout)
 7 #define clr(arr,val) memset(arr,val,sizeof(arr))
 8 #define _for(i,start,end) for(int i=start;i<=end;i++)
 9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
10 using namespace std;
11 typedef long long LL;
12 const int N=2e3+5;
13 const int INF=0x3f3f3f3f;
14 const double eps=1e-10;
15
16 LL dp[N],ub[N];
17 bool rain[N];
18
19 int main(){
20     FAST_IO;
21     int a,n,m;
22     cin>>a>>n>>m;
23     for(int i=0;i<N;i++){
24         dp[i]=ub[i]=1e18;
25     }
26     for(int i=1;i<=n;i++){
27         int l,r;
28         cin>>l>>r;
29         if(l>r) swap(l,r);
30         for(int j=l;j<=r-1;j++){
31             rain[j]=true;
32         }
33     }
34     for(int i=1;i<=m;i++){
35         LL p,w;
36         cin>>p>>w;
37         ub[p]=min(ub[p],w);
38     }
39     dp[0]=0;
40     for(int i=1;i<=a;i++){
41         if(!rain[i-1]){
42             dp[i]=dp[i-1];
43         }
44         else{
45             for(int j=i-1;j>=0;j--){
46                 if(ub[j]!=1e18)
47                     dp[i]=min(dp[i],dp[j]+(i-j)*ub[j]);
48             }
49         }
50     }
51     if(dp[a]==1e18)
52         cout<<-1<<endl;
53     else
54         cout<<dp[a]<<endl;
55     return 0;
56 }

解法二:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<string>
  6 #include<string.h>
  7 #include<cctype>
  8 #include<math.h>
  9 #include<stdlib.h>
 10 #include<stack>
 11 #include<queue>
 12 #include<set>
 13 #include<map>
 14 #define lc(a) (a<<1)
 15 #define rc(a) (a<<1|1)
 16 #define MID(a,b) ((a+b)>>1)
 17 #define fin(name)  freopen(name,"r",stdin)
 18 #define fout(name) freopen(name,"w",stdout)
 19 #define clr(arr,val) memset(arr,val,sizeof(arr))
 20 #define _for(i,start,end) for(int i=start;i<=end;i++)
 21 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
 22 using namespace std;
 23 typedef long long LL;
 24 const int N=2e3+5;
 25 const int INF=0x3f3f3f3f;
 26 const double eps=1e-10;
 27
 28 bool rain[N],flag[N];
 29 LL dp[N][3],ub[N];
 30 //dp[i][0]表示到达第i段不拿伞最小花费
 31 //dp[i][1]表示到达第i段拿伞最小化费
 32 //dp[i][2]表示到达第i段拿最小重量的伞的最小化费
 33
 34 int main(){
 35     FAST_IO;
 36     int a,n,m;
 37     cin>>a>>n>>m;
 38     for(int i=0;i<N;i++){
 39         ub[i]=dp[i][0]=dp[i][0]=dp[i][1]=1e18;
 40     }
 41     for(int i=1;i<=n;i++){
 42         int l,r;
 43         if(l>r)
 44             swap(l,r);
 45         cin>>l>>r;
 46         for(int j=l;j<=r-1;j++){
 47             rain[j]=true;
 48         }
 49     }
 50     for(int i=1;i<=m;i++){
 51         LL p,w;
 52         cin>>p>>w;
 53         ub[p]=min(ub[p],w);
 54     }
 55
 56     if(!rain[0])
 57         dp[0][0]=0;
 58     dp[0][1]=dp[0][2]=ub[0];
 59     LL mmin=ub[0],now=ub[0];
 60     for(int i=1;i<=a-1;i++){
 61         if(ub[i]){
 62             mmin=min(ub[i],mmin);
 63             now=min(ub[i],now);
 64         }
 65         LL t=min(dp[i-1][1]+now,dp[i-1][2]+mmin);
 66         dp[i][1]=t;
 67         if(t==dp[i-1][2]+mmin)
 68             now=mmin;
 69         dp[i][2]=dp[i-1][2]+mmin;
 70
 71         //下雨
 72         if(rain[i]){
 73             //有伞
 74             if(ub[i]){
 75                 dp[i][1]=min(dp[i-1][0]+ub[i],dp[i][1]);
 76                 if(dp[i][1]==dp[i-1][0]+ub[i])
 77                     now=ub[i];
 78                 if(mmin==ub[i]){
 79                     dp[i][2]=min(dp[i-1][0]+mmin,dp[i][2]);
 80                 }
 81             }
 82         }
 83         //不下雨
 84         else{
 85             dp[i][0]=min(dp[i-1][0],dp[i-1][1]);
 86             //有伞
 87              if(ub[i]){
 88                 dp[i][1]=min(dp[i-1][0]+ub[i],dp[i][1]);
 89                 if(dp[i][1]==dp[i-1][0]+ub[i])
 90                     now=ub[i];
 91                 if(mmin==ub[i]){
 92                     dp[i][2]=min(dp[i-1][0]+mmin,dp[i][2]);
 93                 }
 94             }
 95         }
 96     }
 97     LL ans=min(dp[a-1][0],dp[a-1][1]);
 98     if(ans!=1e18)
 99         cout<<ans<<endl;
100     else
101         cout<<-1<<endl;
102     return 0;
103 }

原文地址:https://www.cnblogs.com/fu3638/p/9126288.html

时间: 2024-08-30 05:23:44

Codeforces 988F Rain and Umbrellas(DP)的相关文章

Codeforces F. Rain and Umbrellas

解题思路:动态规划 遍历点i,如果从前一个点i-1走到这个点i不需要伞,则疲劳值不变dp[i] = dp[i-1]. 如果前一个点i-1走到这一个点i需要伞,则从前面找一把伞. 即遍历前面的每个点j,如果点j处有伞,dp[i] = min(dp[i], dp[j]+(i-j)*fig[j]).fig[j]意为第j个点出伞所需要的疲劳值. 代码 #include <bits/stdc++.h> using namespace std; typedef long long ll; bool seg

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/contest/988/problem/E Description Polycarp lives on a coordinate line at the point x=0. He goes to his friend that lives at the point x=a. Polycarp can

Codeforces 360C Levko and Strings dp

题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t对应位置的k个子串字典序>s #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; #

CodeForces 30C Shooting Gallery 简单dp

题目链接:点击打开链接 给定n个气球 下面n行 x y t val 表示气球出现的坐标(x,y) 出现的时刻t,气球的价值val 枪每秒移动1个单位的距离 问: 射击的最大价值,开始时枪瞄准的位置任意. 思路: dp一下.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include

CodeForces 55D Beautiful numbers 数位DP+数学

题意大概是,判断一个正整数区间内有多少个整数能被它自身的每一个非零的数字整除. 因为每一个位置上的整数集s = {0,1,2,3,4,5,6,7,8,9} lcm(s) = 2520 现在有一个整数t是由s中一个或者多个数字构成的,记为abcde,显然t = a*10^4+b*10^3+c*10^2+d*10^1+e 要使得t能被a,b,c,d,e整除,必然有t % lcm(a,b,c,d,e) = 0 因为a,b,c,d,e去重之后一定是s的一个子集,所以lcm(s)一定是lcm(a,b,c,

Rain and Umbrellas(dp)

题目链接 http://codeforces.com/problemset/problem/988/F 令dp[i][j]为走到目标为i处,手里拿着第j把伞,同时注意,在某处可能存在不止一把伞 #include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <queue> #include

Codeforces 833B 线段树优化 dp

Codeforces  833B  The Bakery 题意: n 个数要分成 k 块,每块的价值是其不同数的个数,问价值和最大是多少. tags: dp[i][j]表示前 j 个数分成 i 块的最大权值和,转移: dp[i][j] = max( dp[i-1][k] + val[k+1][j] ) , k是 1~j . 但这个过程其实并不好转移,要利用累加的特点,用线段树进行优化 (感觉我不看题解是想不到的,2333) 大概就是,对于第 i 层,我们假定已经知道了第 i-1 层,也就是求出了