题目链接: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-11-13 09:55:38