题目

最近房地产商 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. Oracle文本导入器

    将文本格式化为Tab分隔的数据行,可以用Excel搞定 如果新增列需要从前面的列获取数据,比如用身份证号计算年龄 需要保证新增列在导入的文件中实际存在列,否则无法使用相对位置和绝对位置进行取值 相对位 ...

  2. Linux---more命令学习

    More命令 more命令一般用于分页显示文件的内容,more会显示文件第一屏的内容,在屏幕的底部,more用反白字体显示文件的百分比,这时如果按空格键,文件的一下屏内容会显示出来,如果按回车键,显示 ...

  3. 【题解】洛谷P1066 [NOIP2006TG] 2^k进制数(复杂高精+组合推导)

    洛谷P1066:https://www.luogu.org/problemnew/show/P1066 思路 挺难的一道题 也很复杂 满足题目要求的种数是两类组合数之和 r的最多位数m为 w/k(当w ...

  4. js读取跨域webapi传送回来的cookie 要点

    1.webapi 返回cookie时,httpOnly=false 2.webapi 接收Origins 不能为* 3.js端 请求时,withCredentials必须: true   //`wit ...

  5. pdf.js 在线阅读PDF

    在网上找了一下如何在线显示pdf文件.个人还是觉得这个是比较不错的,这里做一个记录. gitHub:https://github.com/mozilla/pdf.js           这是一个开源 ...

  6. c语言描述的二叉树的基本操作(层序遍历,递归,非递归遍历)

    #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define ...

  7. EventBus 基础篇

    最近在研究RxJava ,突然想起了事件分发另一个强大的框架Eventbus ,并且项目经常用到,特意整理了下. what is Eventbus? 官方的解释为: EventBus is a pub ...

  8. java 后台返回文件流到浏览器

    package com.springbootblog.controller; import io.swagger.annotations.ApiImplicitParam;import io.swag ...

  9. Excel 批量重命名照片

    理历史照片的时候发现,用文件夹进行分类之后,还有很多照片,如果继续分类,就会导致每个文件夹照片过少,查看不便,但是如果不分类,手机原始的命名方式没有办法满足查看需求,故而,产生了对照片进行批量重命名的 ...

  10. c#常用数据库封装再次升级

    c#封装的几类数据库操作: 1.sqilte 2.berkeleydb 3.一般数据库 4.redis 包含其他项目: 1.序列化 2.通信 3.自定义数据库连接池 再次升级内容: 1.新增redis ...