2021HDU多校第三场 1009 Rise in Price 思维+乱搞

Posted kaka0010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021HDU多校第三场 1009 Rise in Price 思维+乱搞相关的知识,希望对你有一定的参考价值。

原题链接:https://acm.hdu.edu.cn/showproblem.php?pid=6981

题意

有两个n*n的矩阵a,b分别代表每个格子的钻石数量和提升的单价,我们只能从(1,1)开始走到(n,n),问售卖钻石的最大价值是多少。

分析

赛中往DP和网络流方向去想了,很明显发现这个状态根本无法全部表示,记录到当前为止拿到的宝石数量和提升的价格是不可能的,因为这是指数提升的状态。根据题解中描述的,我们只需要取最满足条件的前K个状态保存一下,接着进行合并。

合并的方法也非常简单,只需要利用归并排序的思想,我们将 宝 石 数 ∗ 单 价 宝石数*单价 高的状态往前放一放,只需要O(n)的合并复杂度,粗略计算一下复杂度大约是 O ( T ∗ n 2 K ) O(T*n^2K) O(Tn2K),因此K取100左右就可以了。

Code

#include <bits/stdc++.h>
#define lowbit(i) i & -i
#define Debug(x) cout << x << endl
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PII;
const ll INF = 1e18;
const double eps = 1e-3;
const int N = 1e6 + 10;
const int M = 1e6 + 10;
const int MOD = 998244353;
vector<PII> f[105][105];
int a[105][105], b[105][105];
bool cmp(PII x, PII y) {
    return x.fi * x.se >= y.fi * y.se;
}
void merge(vector<PII> &F, vector<PII> f1, vector<PII> f2) {
    int l = 0, r = 0;
    int SIZE = 105;
    while (l < f1.size() && r < f2.size() && F.size() < SIZE) {
        if (f1[l].fi * f1[l].se >= f2[r].fi * f2[r].se) {
            F.push_back({f1[l].fi, f1[l].se});
            l++;
        } else {
            F.push_back({f2[r].fi, f2[r].se});
            r++;
        }
    }
    while (l < f1.size() && F.size() < SIZE) {
        F.push_back({f1[l].fi, f1[l].se});
        l++;
    }
    while (r < f2.size() && F.size() < SIZE) {
        F.push_back({f2[r].fi, f2[r].se});
        r++;
    }
    sort(F.begin(), F.end(), cmp);
}
void solve() {
    int T; cin >> T; while (T--) {
        int n; cin >> n;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                cin >> a[i][j];
                f[i][j].clear();
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                cin >> b[i][j];
            }
        }
        f[1][1].push_back({a[1][1], b[1][1]});
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (i == 1 && j == 1) continue;
                else if (i == 1) f[i][j] = f[i][j-1];
                else if (j == 1) f[i][j] = f[i-1][j];
                else merge(f[i][j], f[i-1][j], f[i][j-1]);
                for (auto &it : f[i][j]) it.fi += a[i][j], it.se += b[i][j];
            }
        }
        ll ans = 0;
        for (int i = 0; i < f[n][n].size(); i++) {
            ans = max(ans, f[n][n][i].fi * f[n][n][i].se);
        }
        cout << ans << endl;
    }
}
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

以上是关于2021HDU多校第三场 1009 Rise in Price 思维+乱搞的主要内容,如果未能解决你的问题,请参考以下文章

多校第三场 Rise in Price(模拟)

2018 HDU多校第三场赛后补题

《HDU多校第三场》

hdu多校第三场 1006 (hdu6608) Fansblog Miller-Rabin素性检测

2020hdu多校第三场1005(6795)Little W and Contest

hdu多校第三场 1007 (hdu6609) Find the answer 线段树