It is the middle of 2018 and Maria Stepanovna, who lives outside Krasnokamensk (a town in Zabaikalsky region), wants to rent three displays to highlight an important problem.
There are si<sj<sk should be held.
The rent cost is for the ci. Please determine the smallest cost Maria Stepanovna should pay.
The first line contains a single integer 3≤n≤3000) — the number of displays.
The second line contains 1≤si≤109) — the font sizes on the displays in the order they stand along the road.
The third line contains 1≤ci≤108) — the rent costs for each display.
If there are no three displays that satisfy the criteria, print -1. Otherwise print a single integer — the minimum total rent cost of three displays with indices si<sj<sk.
5
2 4 5 4 10
40 30 20 10 40
90
3
100 101 100
2 4 5
-1
10
1 2 3 4 5 6 7 8 9 10
10 13 11 14 15 12 13 13 18 13
33
In the first example you can, for example, choose displays 40+10+40=90.
In the second example you can't select a valid triple of indices, so the answer is -1.
题意:选三个数,要求:i<j<k 且a[i]<a[j]<a[k],要求选出来的三个数的权值最小
思路:开始总想的是贪心,二分啥啥啥的。。。结果仔细想了下,他的范围是3000, O(n^3)的时间复杂度肯定不行,O(n^2)就可以过
只要我预处理第三个数,在每个数这从后面找一个权值最小且大于它的数,以此来作为第三个数即可,后面只要枚举两个数即可
#include<cstdio> #include<cmath> #include<iostream> #define ll long long using namespace std; ll a[5000],b[5000],dp[5000]; int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) scanf("%d",&b[i]); for(int i=0;i<n;i++) { ll mn=99999999999; for(int j=i+1;j<n;j++) { if(a[i]<a[j]) { mn=min(mn,b[j]); } } dp[i]=mn; } ll ans=999999999999; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { if(a[i]<a[j]) { if(dp[j]!=99999999999) ans=min(ans,b[i]+b[j]+dp[j]); } } } if(ans==999999999999) printf("-1\n"); else cout<<ans<<endl; }
总结:总的来说这次cf div2的题目不是很难,只是自己刷提还是刷的太少了,没想到思路就卡到了,训练太少,刷题太慢,需要好好反省
规律题总结,看到那种遍历一遍就超时那就肯定是规律题,一 班自己先把公式推出来,然后写个小枚举,把答案输出出来,然后自己再把递推公式推出来,再求解即可