2025“钉耙编程”中国大学生算法设计暑期联赛(1)——1006景区建设(诈骗题) · znzryb
## 思路讲解
$114∣x_1−x_2∣+5141∣y_1−y_2∣+919810|a_x - a_y|$
这个式子看着很唬人,其实还可以,不难发现
$114*100+5141*100-919810=
-394310$
所以说就不用考虑这个x,也不用考虑这个y,只需要考虑高度(即a)就可以了。
找**局部最高点**也只需要这段代码(把旁边的四个格子扫一圈就行)。
```cpp
FOR(i,1,N){
FOR(j,1,M){
// 已经布设了传送门
if(i==1 && j==1) continue;
bool isHi=true;
FOR(k,0,3){
ll x=i+dx[k],y=j+dy[k];
if(x<1 || x>N) continue;
if(y<1 || y>M) continue;
if(A[x][y]>A[i][j]){
isHi=false;
break;
}
}
if(isHi){
ans+=cs;
wp.EB(i,j);
}
}
}
```
## AC代码
[https://acm.hdu.edu.cn/contest/view-code?cid=1172&rid=19896](https://acm.hdu.edu.cn/contest/view-code?cid=1172&rid=19896)
::: 源代码
```cpp
// Problem: 景区建设
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/contest/problem?cid=1172&pid=1006
// Memory Limit: 65536 MB
// Time Limit: 1000 ms
// by gospel_rock
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define all(vec) vec.begin(),vec.end()
#define pb push_back
#define EB emplace_back
#define EM emplace
#define FI first
#define SE second
#define SZ(a) ((int) a.size())
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(var) cerr << #var <<":"<<var<<"\n";
#define lson(var) (var<<1)
#define rson(var) ((var<<1)+1)
using namespace std;
using ll = long long;using ull = unsigned long long;
using DB=double;using LD=long double;
using i128 = __int128;
using pdd = pair<DB,DB>;using plb = pair<ll,bool>;
using pll = pair<ll,ll>;using vll=vector<ll>;using vb=vector<bool>;
using vpll=vector<pll>;
using arr3 = array<ll,3> ;using arr2 = array<ll,2>;
constexpr ll MAXN=(ll)1e2+10,INF=(ll)1e17+9; // 1e18+9也是素数
constexpr ll MAXV=(ll)1e6+10;
constexpr ll MAXM=(ll)2e6+10;
constexpr ll mod=(ll)1e9+7; // 998244353
constexpr double eps=1e-8;const double pi=acos(-1.0);
ll N,M,Q,X,K,T,lT;
ll A[MAXN][MAXN];
/*
*/
ll binpow(ll a,ll k){ // 迭代快速幂
ll res=1; // 防止a*a溢出
while(k>0){
if((k&1)==1) res=a*res;
a=a*a;
k>>=1;
}
return res;
}
const ll cs=binpow(2,34);
/* ->
| |
<-
*/
ll dx[4]={0,1,0,-1};
ll dy[4]={1,0,-1,0};
std::istream& operator>>(std::istream& is, __int128& x) {
std::string s;
is >> s;
x = 0;
bool negative = false;
// 处理负号
size_t i = 0;
if (s[0] == '-') {
negative = true;
i = 1;
}
// 将字符串转换为 __int128
for (; i < s.length(); ++i) {
x = x * 10 + (s[i] - '0');
}
if (negative) {
x = -x;
}
return is;
}
std::ostream& operator<<(std::ostream& os, __int128 x) {
if (x == 0) {
return os << "0";
}
if (x < 0) {
os << '-';
x = -x;
}
// 将 __int128 转换为字符串
std::string s;
while (x > 0) {
s.push_back((x % 10) + '0');
x /= 10;
}
// 反转字符串以得到正确顺序
for (int i = s.length() - 1; i >= 0; --i) {
os << s[i];
}
return os;
}
bool cmp(const pll &a,const pll &b){
return A[a.FI][a.SE]<A[b.FI][b.SE];
}
inline void __(){
cin>>N>>M;
FOR(i,1,N){
FOR(j,1,M){
cin>>A[i][j];
}
}
i128 ans=0;
vpll wp;
FOR(i,1,N){
FOR(j,1,M){
// 已经布设了传送门
if(i==1 && j==1) continue;
bool isHi=true;
FOR(k,0,3){
ll x=i+dx[k],y=j+dy[k];
if(x<1 || x>N) continue;
if(y<1 || y>M) continue;
if(A[x][y]>A[i][j]){
isHi=false;
break;
}
}
if(isHi){
ans+=cs;
wp.EB(i,j);
}
}
}
wp.EB(1,1);
sort(all(wp),cmp);
FOR(i,0,SZ(wp)-2){
auto &[x,y]=wp[i];auto &[xx,yy]=wp[i+1];
ans+=114*abs(xx-x)+5141*abs(yy-y)+919810*abs(A[x][y]-A[xx][yy]);
}
cout<<ans<<"\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>lT;
while(lT--)
__();
return 0;
}
/*
AC
https://acm.hdu.edu.cn/contest/view-code?cid=1172&rid=19896
*/
```
:::
## 心路历程(WA,TLE,MLE……)