1. 程式人生 > >Codeforces 988F Rain and Umbrellas(DP)

Codeforces 988F Rain and Umbrellas(DP)

sync star ctype cto int lib pre TE 相同

題目鏈接: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 }

Codeforces 988F Rain and Umbrellas(DP)