题目

最近房地产商 GDOI (Group of Dumbbells Or Idiots) 从 NOI (Nuts Old Idiots) 手中得到了一块开发土地。

据了解,这块土地是一块矩形的区域,可以纵横划分为 \(N\times M\) 块小区域。GDOI 要求将这些区域分为商业区和工业区来开发。

根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值。更具体点,对于第 \(i\) 行第 \(j\) 列的区域,建造商业区将得到 \(A_{ij}\) 收益,建造工业区将得到 \(B_{ij}\) 收益。

另外,不同的区域连在一起可以得到额外的收益,即如果区域\((I,j)\)相邻(相邻是指两个格子有公共边)有 \(K\) 块(显然 \(K\) 不超过 \(4\))类型不同于\((I,j)\)的区域,则这块区域能增加 \(k\times C_{ij}\) 收益。

经过 Tiger.S 教授的勘察,收益矩阵 \(A,B,C\) 都已经知道了。你能帮 GDOI 求出一个收益最大的方案么?

分析

网络流是不可能网络流的, 这辈子都不可能网络流的.

我发现有 \(2^{nm}\) 种解, 然而答案范围只有 \(1000nm\), 说明有大量的重复解, 那还写正解?

这道题我用模拟退火, 随机的是一个矩阵代表每个地方是什么区域.

每次随机一个点做一些微小的变化就可以了.

(如果调参调不下去可以试试多退火几次, 跳出局部最优)

比如我是这样写的:

int ans = 0;
for(int i = 0; i < 42; i++)
ans = std::max(SA(), ans);
printf("%d", ans);

代码

(不保证每时每刻你提交这份都能 AC)

#include <bits/stdc++.h>

const int kMaxSize = 105, mod = 1e9 + 7;
const double delta = 0.994, sup = 1e17, eps = 1e-17; bool plan[kMaxSize][kMaxSize];
int n, m, a[kMaxSize][kMaxSize], b[kMaxSize][kMaxSize], c[kMaxSize][kMaxSize]; unsigned sed = time(NULL);
inline unsigned Rand() {
sed = ((sed * 0x3abcd1ac + 0xabc12ab2) ^ (sed + 0x1230bace)) % mod;
return sed;
} int GetIncome() {
int ans = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++) {
if(plan[i][j]) ans += a[i][j];
else ans += b[i][j];
if(i - 1 >= 0 && plan[i - 1][j] != plan[i][j]) ans += c[i][j];
if(j - 1 >= 0 && plan[i][j - 1] != plan[i][j]) ans += c[i][j];
if(i + 1 < n && plan[i + 1][j] != plan[i][j]) ans += c[i][j];
if(j + 1 < m && plan[i][j + 1] != plan[i][j]) ans += c[i][j];
}
return ans;
} inline int change(int ans, int x, int y) {
plan[x][y] ^= 1;
ans += plan[x][y] ? a[x][y] - b[x][y] : b[x][y] - a[x][y];
if(x - 1 >= 0) {
ans += plan[x - 1][y] != plan[x][y] ?
c[x][y] + c[x - 1][y] : -(c[x][y] + c[x - 1][y]);
}
if(y - 1 >= 0) {
ans += plan[x][y - 1] != plan[x][y] ?
c[x][y] + c[x][y - 1] : -(c[x][y] + c[x][y - 1]);
}
if(x + 1 < n) {
ans += plan[x + 1][y] != plan[x][y] ?
c[x][y] + c[x + 1][y] : -(c[x][y] + c[x + 1][y]);
}
if(y + 1 < m) {
ans += plan[x][y + 1] != plan[x][y] ?
c[x][y] + c[x][y + 1] : -(c[x][y] + c[x][y + 1]);
}
return ans;
} int SA() {
register int ans, old_ans, new_ans, cnt = 0;
ans = old_ans = GetIncome();
for(register double T = sup; T > eps; T *= delta) {
int x = Rand() % n, y = Rand() % m;
new_ans = change(old_ans, x, y);
ans = new_ans > ans ? new_ans : ans;
if(new_ans > old_ans ||
Rand() <= exp((new_ans - old_ans) * 1.0 / T) * mod)
old_ans = new_ans;
else plan[x][y] ^= 1;
cnt++;
}
return ans;
} int main() {
srand(time(NULL));
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &a[i][j]);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &b[i][j]);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &c[i][j]);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
plan[i][j] = a[i][j] > b[i][j];
int ans = 0;
for(int i = 0; i < 42; i++)
ans = std::max(SA(), ans);
printf("%d", ans);
return 0;
}

结语

不过, Luogu的数据貌似有点水, 这个代码在一些地方貌似过不了?

【Luogu P1935】[国家集训队]圈地计划的更多相关文章

  1. 洛谷P1935 [国家集训队]圈地计划

    题目大意: 有个\(n*m\)的网格图 每个点可以选择\(A\),获得\(A[i][j]\)或选\(B\)获得\(B[i][j]\)的收益 相邻点有\(k\)个不同可以获得\(C[i][j]\)的收益 ...

  2. 洛谷$P1935$ [国家集训队]圈地计划 网络流

    正解:最小割 解题报告: 传送门 就文理分科模型嘛$QwQ$?所以就,跑个最小割呗,然后就做完辣?仔细想想细节发现并麻油那么简单嗷$QwQ$ 先考虑如果没有这个$k\cdot C_{i,j}$的贡献就 ...

  3. luogu P2757 [国家集训队]等差子序列

    题目链接 luogu P2757 [国家集训队]等差子序列 题解 线段树好题 我选择暴力 代码 // luogu-judger-enable-o2 #include<cstdio> inl ...

  4. luogu P2619 [国家集训队2]Tree I

    题目链接 luogu P2619 [国家集训队2]Tree I 题解 普通思路就不说了二分增量,生成树check 说一下坑点 二分时,若黑白边权有相同,因为权值相同优先选白边,若在最有增量时出现黑白等 ...

  5. [Luogu P1829] [国家集训队]Crash的数字表格 / JZPTAB (莫比乌斯反演)

    题面 传送门:洛咕 Solution 调到自闭,我好菜啊 为了方便讨论,以下式子\(m>=n\) 为了方便书写,以下式子中的除号均为向下取整 我们来颓柿子吧qwq 显然,题目让我们求: \(\l ...

  6. Luogu P1297 [国家集训队]单选错位

    P1297 [国家集训队]单选错位 题目背景 原 <网线切割>请前往P1577 题目描述 gx和lc去参加noip初赛,其中有一种题型叫单项选择题,顾名思义,只有一个选项是正确答案.试卷上 ...

  7. Luogu P2619 [国家集训队2]Tree I(WQS二分+最小生成树)

    P2619 [国家集训队2]Tree I 题意 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有\(need\)条白色边的生成树. 题目保证有解. 输入输出格式 输入格式 ...

  8. 【luogu P1494 [国家集训队]小Z的袜子】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1494 #include <cstdio> #include <algorithm> ...

  9. 【luogu P1903 [国家集训队]数颜色】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1903 裸的...带修莫队... 比较麻烦吧(对我来说是的) 两个变量分开记录查询和修改操作. #includ ...

随机推荐

  1. 【[SDOI2014]旅行】

    听说这是动态开点主席树的板子题,但是发现我还不会,于是就来写一写 其实跟主席树一个样子的 这里就是存个板子吧 #include<cstdio> #include<cstring> ...

  2. 2018.12.14 Mac的Matlab2018a软件及其安装步骤

    软件百度云链接:https://pan.baidu.com/s/1q3EO5up-1YuAQ4gEi7sTwQ 密码:p6mf MATLAB R2018a for Mac破解说明 1.MATLAB R ...

  3. [转]CUDA和OpenGL互操作的实现及分析

    CUDA和OpenGL互操作的实现及分析刘进锋.郭雷(西北工业大学 自动化学院,陕西西安710129) 1 CUDA与OpenGL概述 OpenGL是图形硬件的软件接口,它是在SGI等多家世界著名的计 ...

  4. Nodejs做整站转发

    刚接触nodejs,做个东西练下手,通过nodejs直接转发整站,原本想把内容全翻译成英文,但google对流量行审查,被封IP,所以就没啥用了, 效果像这样 var b = function (a, ...

  5. 使用transfor让图片旋转

    材料:Transform,onmouseout,onmouseover css: html: js:

  6. ATK-DataPortal 设计框架(一)

    无论是简单的还是复杂的框架,总需要一个开始的原点,ATK-DataPortal中包含了所有基础类的定义. 一.业务框架基础类 1.BusinessBase:所有业务类的根类,要使用ATK库的类,必需继 ...

  7. Web前端几种常见的实现水平垂直居中的方法

    第一种: 父容器不设置宽度,用定位实现水平垂直居中. <!DOCTYPE html> <html lang="en"> <head> <m ...

  8. c++stl应用入门

    在这篇中,我会讲几个简单易懂且比较常用的stl函数,这些函数在noip系列考试中往往被允许使用(既然让用我们自然不用手码了...) (末尾有惊喜!) 1.sort 绝大部分刚入门的oier第一个接触的 ...

  9. 范围for语句的整理

    1.如何处理stirng中的每个字符?(来自C++Primer中文版5th中P83) 使用基于范围的for语句,比如下面的例子,输出每个字符 #include<iostream> #inc ...

  10. leetcode笔记(三)207. Course Schedule

    题目描述(原题目链接) There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may ...