CF C. Three displays(DP+思维)
http://codeforces.com/contest/987/problem/C
题意:给你两个n的序列要你根据第一个序列(严格单调递增的方式)在第二个序列里找3个数加起来,输出最小的一个。
思路:先从前往后枚举两个最小的。在从后往前找一个加上使其最小,最后遍历剩下的三元组。
AC代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=4000; const int INF=4*1e9; struct node{ int num,id; }; struct node1{ ll h,Sum; }; node a[maxn]; node1 sum[maxn]; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ sum[i].Sum=INF; } for(int i=1;i<=n;i++){ cin>>a[i].id; } for(int i=1;i<=n;i++){ cin>>a[i].num; } ll Min=4*1e9; for(int i=1;i<=n-1;i++){ Min=4*1e9; for(int j=i+1;j<=n;j++){ if(a[i].id<a[j].id){ if(a[i].num+a[j].num<Min) { Min=a[i].num+a[j].num; } } } sum[i].Sum=Min; sum[i].h=2; } //cout<<sum[2].Sum<<endl; for(int i=n-1;i>=2;i--){ Min=4*1e9; for(int j=i-1;j>=1;j--){ if(a[i].id>a[j].id){ if(sum[i].Sum+a[j].num<Min){ Min=sum[i].Sum+a[j].num; } } } sum[i].Sum=Min; sum[i].h=3; } Min=4*1e9; int i,k; for( i=1;i<=n;i++){ if(Min>sum[i].Sum&&sum[i].h==3){ Min=sum[i].Sum; k=i; } } if(Min<INF){ cout<<Min<<endl; } else cout<<"-1"<<endl; return 0; }
大神:
#include <bits/stdc++.h> using namespace std; const int maxn=3010,inf=0x3f3f3f3f; int s[maxn],c[maxn],f[maxn],dp[maxn]; int n,ans; int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&s[i]); for (int i=1;i<=n;i++) scanf("%d",&c[i]); dp[1]=inf; for (int i=2;i<=n;i++){ dp[i]=inf; for (int j=i-1;j>=1;j--){ if(s[i]>s[j]) dp[i]=min(dp[i],c[i]+c[j]); } // printf("%d ",dp[i]); } // printf("\n"); ans=inf; for (int i=3;i<=n;i++){ f[i]=inf; for (int j=i-1;j>=1;j--){ if(s[j]<s[i]) f[i]=min(f[i],c[i]+dp[j]); } // printf("%d ",f[i]); ans=min(ans,f[i]); } // printf("\n"); if(ans==inf) puts("-1"); else printf("%d\n",ans); return 0; }