D.遗迹探索
题目链接:D-遗迹探险_牛客小白月赛72(重现赛)@XuSihan (nowcoder.com)
思路:定义两个DP数组,第一个DP数组用来存储从(1, 1)到任何位置所能获得的最大宝藏价值,第二个DP数组用来存储从(n, m)到任何位置所能获得的最大宝藏价值,因为传送门的数据范围较小,所以我们可以枚举任意两个传送门的位置,求经过这两个传送门后所能获得的最大宝藏价值,最后把枚举的所有价值中取最大的那个即可(因为宝藏有负权价值,所以还有一种情况就是不走任何传送门直接从(1, 1)走到(n, m))
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
#define x first
#define y second
#define endl '\n'
typedef long long ll;
const int mod=998244343;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
#define int long long
const int N=2010;
int a[N][N];
int dp1[N][N],dp2[N][N];
void solve()
{
int n,m,t;
cin>>n>>m;
memset(dp1, -0X3f, sizeof dp1);
memset(dp2, -0X3f, sizeof dp2);
dp1[1][0]=dp1[0][1]=0;
dp2[n+1][m]=dp2[n][m+1]=0;
for(int i = 1;i<=n;i++)
for(int j = 1;j<=m;j++)
{
cin>>a[i][j];
dp1[i][j]=max(dp1[i-1][j],dp1[i][j-1])+a[i][j];
}
for(int i = n;i>=1;i--)
for(int j = m;j>=1;j--)
{
dp2[i][j]=max(dp2[i+1][j], dp2[i][j+1])+a[i][j];
}
cin>>t;
while(t --)
{
int k;cin>>k;
vector<PII> v;
for(int i = 1;i<=k;i++)
{
int n1,m1;cin>>n1>>m1;
v.push_back({n1,m1});
}
int ans=dp2[1][1];
for(int i=0;i<v.size();i++)
{
for(int j=0;j<v.size();j++)
{
if(i==j)continue;
ans=max(ans,dp1[v[i].x][v[i].y]+dp2[v[j].x][v[j].y]);
}
}
cout<<ans<<endl;
}
}
signed main()
{
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
int T=1;
// cin>>t;
while(T--) solve();
return 0;
}
E.顶级厨师
题目链接:E-顶级厨师_牛客小白月赛72(重现赛)@XuSihan (nowcoder.com)
本题进行二分算法进行计算
#include<bits/stdc++.h>
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010;
int a[N], b[N];
ll c[1000010];
ll n, m, k, q,u;
bool check(ll t)
{
ll sum = 0;
for (int l = 1, r = m; l <= n; l++)
{
while (a[l] * b[r] > t && r) r--;
sum += r;
}
for (int i = 1; i <= k; i++) if (c[i] <= t) sum--;
return sum>=u;
}
void solve()
{
cin >> n>>m>>k>>q;
for (int i = 1; i <=n; i++) cin >> a[i];
for (int i = 1; i <=m; i++) cin >> b[i];
for (int i = 1; i <= k; i++)
{
int x, y;
cin >> x >> y;
c[i] = a[x] * b[y];
}
sort(a + 1, a + n + 1);
sort(b + 1, b + m + 1);
while (q--)
{
cin >> u;
ll l = 0, r = 1e12;
while (l < r)
{
ll mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << l << endl;
}
}
int main()
{
IOS;
int t = 1;
while (t--) solve();
return 0;
}