题目

最近房地产商 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. 【luogu P1462 通往奥格瑞玛的道路】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1462 记住HP=0也叫死. #include <queue> #include <cstd ...

  2. c++ 单继承派生类的构造函数

    1.派生类的构造函数: #include <iostream> #include<string> using namespace std; class Student//声明基 ...

  3. GYM 101550 G.Game Rank(模拟)

    The gaming company Sandstorm is developing an online two player game. You have been asked to impleme ...

  4. Linux CentOS7下安装Zookeeper-3.4.10服务(最新)

    Linux CentOS7下安装Zookeeper-3.4.10服务(最新) 2017年10月27日 01:25:26 极速-蜗牛 阅读数:1933   版权声明:本文为博主原创文章,未经博主允许不得 ...

  5. zepto 基础知识(1)

    1.$() 的用法. 获取元素 $('div') //获取所有页面中的div元素 $('#foo') // 获取ID 为"foo"的元素 创建元素 $("<p> ...

  6. Vue--- mint-UI 穿插

    Vue-mint-UI库 概述:就是一个 封装好的库 安装/下载:npm install  --save mint-ui 常用 1) Mint UI:a. 主页: http://mint-ui.git ...

  7. JSONP--解决ajax跨域问题

    JSON和JSONP JSONP和JSON好像啊,他们之间有什么联系吗? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.对于JSON大家应该是很了解了吧 ...

  8. Javascript的加载

    最新博客站点:欢迎来访 1. 浏览器加载     (1) 同步加载 在网页中,浏览器加载js文件的方式是通过<script>标签.如下所示: //内嵌脚本 <script type= ...

  9. 【剑指offer】 Java实现重建二叉树

    GitHub上的代码链接 /** * @Author: DaleyZou * @Description: 重建二叉树 * 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树. * 假设输入的前序 ...

  10. C++练习--创建Boat类和Car类(含友元)

    /* 定义Boat与Car两个类,二者都有weight属性, 定义二者的一个友元函数totalWeight()为外部函数, 计算二者的重量和. */ #include<iostream> ...