CF2096C Wonderful City R1700

题目:
你是古伯兰国一座城市的骄傲领导者。城市中有 ( n^2 ) 栋建筑,排列成 ( n ) 行 ( n ) 列的网格。第 ( i ) 行、第 ( j ) 列的建筑高度为 ( h_{i,j} )。
任意相邻(左右或上下)的两栋建筑高度都不相同,则称这座城市是“美丽的”。
A公司有 ( n ) 名工人,B公司也有 ( n ) 名工人。每名工人最多只能被雇佣一次。

  • 雇佣A公司的工人 ( i ) 需要花费 ( a_i ) 枚硬币。雇佣后,工人 ( i ) 会将第 ( i ) 行的所有建筑高度增加1。
  • 雇佣B公司的工人 ( j ) 需要花费 ( b_j ) 枚硬币。雇佣后,工人 ( j ) 会将第 ( j ) 列的所有建筑高度增加1。

请找出让城市变得美丽所需的最少硬币数;若无法实现,则输出“不可能”。

(还是要好好读题,每行每列都只能加一次,那题目就简单多了///)

思路:
1.显然,给行增加不会改变列的情况,给一列增加也不会改变行的情况,于是考虑行列分开讨论。
2.简单的dp : dp[i][0(1)]表示不改变(改变)第i列的情况下满足前i列美丽的钱数,转移方程:dp[i][0] = min(dp[i - 1][1], dp[i - 1][0]) ,dp[i][1] = min(dp[i - 1][1], dp[i - 1][0]) + a[i]
3.对列同样处理,但是如果不满足就要赋值为inf

code

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
#define int long long
const int inf = 1e18;
int height[maxn][maxn], dp[maxn][2];

void solve() {
    int n; cin>>n;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin>>height[i][j];
        }
    }
    int ans = 0;
    vector<int> a(n + 1, 0), b(n + 1, 0);
    for (int i = 1; i <= n; ++i) cin>>a[i];
    for (int i = 1; i <= n; ++i) cin>>b[i];
    dp[1][0] = 0, dp[1][1] = a[1];
    for (int i = 2; i <= n; ++i) {
        int u = dp[i - 1][0], v = dp[i - 1][1];
        int flag1 = 1, flag2 = 1;
        for (int j = 1; j <= n; ++j) {
            if (height[i - 1][j] == height[i][j]) flag1 = 0;
            if (height[i - 1][j] + 1 == height[i][j]) flag2 = 0;
        }
        if (!flag1) u = inf;
        if (!flag2) v = inf;
        dp[i][0] = min(u, v);
        flag1 = 1, flag2 = 1;
        u = dp[i - 1][0], v = dp[i - 1][1];
        for (int j = 1; j <= n; ++j) {
            if (height[i - 1][j] == height[i][j] + 1) flag1 = 0;
            if (height[i - 1][j] == height[i][j]) flag2 = 0;

        }
        if (!flag1) u = inf;
        if (!flag2) v = inf;
        dp[i][1] = min(u, v) + a[i];

    }
    ans = min(dp[n][0], dp[n][1]);
    for (int i = 0; i <= n; ++i) {
        dp[i][0] = 0, dp[i][1] = 0;
    }
    dp[1][1] = b[1];
    for (int i = 2; i <= n; ++i) {
        int u = dp[i - 1][0], v = dp[i - 1][1];
        int flag1 = 1, flag2 = 1;
        for (int j = 1; j <= n; ++j) {
            if (height[j][i - 1] == height[j][i]) flag1 = 0;
            if (height[j][i - 1] + 1 == height[j][i]) flag2 = 0;
        }
        if (!flag1) u = inf;
        if (!flag2) v = inf;
        dp[i][0] = min(u, v);
        flag1 = 1, flag2 = 1;
        u = dp[i - 1][0], v = dp[i - 1][1];
        for (int j = 1; j <= n; ++j) {
            if (height[j][i - 1] == height[j][i] + 1) flag1 = 0;
            if (height[j][i - 1] == height[j][i]) flag2 = 0;
        }
        if (!flag1) u = inf;
        if (!flag2) v = inf;
        dp[i][1] = min(u, v) + b[i];

    }
    ans += min(dp[n][0], dp[n][1]);
    if (ans >= inf) {
        cout<<-1<<endl;
    }
    else cout<<ans<<endl;

}

signed main() {
    int tt; cin>>tt;
    while (tt--) solve();
    return 0;
}
posted @ 2025-12-22 10:06  Wuyou2008  阅读(1)  评论(0)    收藏  举报