ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 biology

2021-07-11 19:02:36  阅读:164  来源: 互联网

标签:biology int 题解 复杂度 long spfa dp define


传送门

赛时靠spfa求最长路骗了30pts

  • spfa的时间复杂度是\(O(k|E|)\),不是\(O(k|N|)\)!
  • dijkstra 时间复杂度\(O((n+m)logn)\)
  • 特别注意这两个的复杂度都和边数密切相关

spfa的话按a值分层,按层建边即可
正解是个dp,考场上想到dp,但dp思路错了
令\(dp[i][j]\)为在\((i, j)\)位置结束时的最大和

\[dp[i][j] = max(b[i][j]+dp[i'][j']+|i-i'|+|j-j'|) \]

又一个带绝对值的题,可以分情况讨论
对于一个点\((i, j)\),可以用四个二维树状数组分别维护\(i,j\)为正,负时的最大值,
根据点\((i, j)\)和\((i', j')\)的位置关系查询即可,复杂度\(O(nmlognlogm)\)

但是还有一种\(O(nm)\)的解法:

题面里那个 \(|i-i'|+|j-j'|\) 其实是曼哈顿距离
这里我们要求其最大值

  • 曼哈顿距离在处理绝对值时,常转换为切比雪夫距离以简化计算

考虑转化为切比雪夫距离,那方程可以化为

\[dp[i][j] = b[i][j]+max(dp[i'][j']+max(|i-i'|,|j-j'|)) \]

要求距离尽可能大,所以我们可以维护全局 \(max\ \{dp[i'][j']+i', dp[i'][j']-i', dp[i'][j']+j', dp[i'][j']-j'\}\), 转移时用这个分情况转移
yysy,我因为脑残没仔细看题面a=0的点舍弃从下午3点调到6点

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x7fffffffffff
#define N 2010
#define ll long long 
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long 

#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;

namespace force{
	int tot, pos;
	int head[N*N], size, lim[N*N], lcnt; ll dis[N*N];
	bool vis[N*N];
	int ss, st;
	struct point{int a, b, x, y, rk; ll w;}mp[N*N];
	inline bool operator < (point a, point b) {return a.a<b.a;}
	struct edge{int to, next, val;}e[N*N*3];
	inline void add(int s, int t, int w) {edge* k=&e[++size]; k->to=t; k->val=w; k->next=head[s]; head[s]=size;}
	void spfa(int s) {
		queue<int> q;
		dis[s]=0; vis[s]=1; q.push(s);
		int t;
		while (q.size()) {
			t=q.front(); q.pop();
			vis[t]=0;
			for (int i=head[t],v; i; i=e[i].next) {
				v = e[i].to;
				//cout<<t<<": "<<dis[t]<<' '<<mp[t].w<<' '<<e[i].val<<' '<<dis[v]<<endl;
				if (dis[t]+mp[t].w+e[i].val < dis[v]) {
					dis[v] = dis[t]+mp[t].w+e[i].val;
					if (!vis[v]) q.push(v);
				}
			}
		}
		//cout<<"dis: "; for (int i=1; i<=tot+2; ++i) cout<<dis[i]<<' '; cout<<endl;
	}
	void solve() {
		tot=0; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) mp[++tot].a=read(), mp[tot].x=i, mp[tot].y=j, mp[tot].rk=tot;
		tot=0; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) mp[++tot].w=-read();
		sort(mp+1, mp+tot+1);
		//for (int i=1; i<=tot; ++i) cout<<mp[i].a<<' '; cout<<endl;
		for (pos=1; pos<=tot; ++pos) if (mp[pos].a!=mp[pos-1].a) lim[++lcnt]=pos;
		lim[++lcnt]=tot+1;
		for (int i=1; i<=tot+10; ++i) dis[i]=INF;
		ss=tot+1; st=tot+2;
		for (int i=lim[1]; i<lim[2]; ++i) add(ss, i, 0); //, cout<<"ss: "<<ss<<' '<<i<<endl;
		for (int i=lim[lcnt-1]; i<=tot; ++i) add(i, st, 0); //, cout<<"st: "<<i<<' '<<st<<endl;
		for (int i=1; i<lcnt; ++i) {
			for (int j=lim[i]; j<lim[i+1]; ++j) {
				for (int k=lim[i+1]; k<lim[i+2]; ++k) add(j, k, -(abs(mp[j].x-mp[k].x)+abs(mp[j].y-mp[k].y))); //, cout<<"add "<<j<<' '<<k<<' '<<-(abs(mp[j].x-mp[k].x)+abs(mp[j].y-mp[k].y))<<endl;
			}
		}
		spfa(ss);
		printf("%lld\n", -dis[st]);
	}
}

namespace task{
	// 0->i 1->-i 2->j 3->-j
	int tot, lcnt, pos[4], pos2;
	ll maxn[4], dp[N*N], ans;
	struct point{int a, i, j; ll b;}p[N*N];
	inline bool operator < (point a, point b) {return a.a<b.a;}
	struct line{int l, r; inline void build(int l_, int r_) {l=l_; r=r_;}}lin[N*N];
	void solve() {
		memset(maxn, 128, sizeof(maxn));
		tot=0; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) p[++tot].a=read(), p[tot].i=i+j, p[tot].j=i-j;
		tot=0; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) p[++tot].b=read();
		sort(p+1, p+tot+1);
		for (pos2=1; !p[pos2].a; ++pos2) ;
		for (int i=pos2; i<=tot; ++i) {
			lin[++lcnt].l=i;
			for (int j=i+1; j<=tot&&(p[j].a==p[j-1].a); ++i,++j) ;
			lin[lcnt].r=i;
		}
		//for (int i=1; i<=lcnt; ++i) cout<<lin[i].l<<","<<lin[i].r<<endl;
		//for (int i=1; i<=tot; ++i) cout<<p[i].i<<' '<<p[i].j<<endl;
		int i1, j1;
		for (int j=lin[1].l; j<=lin[1].r; ++j) {
			i1=p[j].i, j1=p[j].j;
			dp[j] = p[j].b;
			ans = max(ans, dp[j]);
		}
		for (int j=lin[1].l; j<=lin[1].r; ++j) {
			i1=p[j].i, j1=p[j].j;
			//cout<<"ij: "<<i1<<' '<<j1<<endl;
			maxn[0] = max(maxn[0], dp[j]+i1);
			maxn[1] = max(maxn[1], dp[j]-i1);
			maxn[2] = max(maxn[2], dp[j]+j1);
			maxn[3] = max(maxn[3], dp[j]-j1);
		}
		//cout<<"ans: "<<ans<<endl;
		//cout<<"maxn: "; for (int i=0; i<4; ++i) cout<<maxn[i]<<' '; cout<<endl;
		for (int i=2; i<=lcnt; ++i) {
			for (int j=lin[i].l; j<=lin[i].r; ++j) {
				i1=p[j].i, j1=p[j].j;
				dp[j] = p[j].b+max(max(max(maxn[0]-i1, maxn[1]+i1), maxn[2]-j1), maxn[3]+j1);
				//cout<<"ans in "<<maxn[0]-i1<<' '<<maxn[1]+i1<<' '<<maxn[2]-j1<<' '<<maxn[3]+j1<<endl;
				ans = max(ans, dp[j]);
			}
			for (int j=lin[i].l; j<=lin[i].r; ++j) {
				i1=p[j].i, j1=p[j].j;
				maxn[0] = max(maxn[0], dp[j]+i1);
				maxn[1] = max(maxn[1], dp[j]-i1);
				maxn[2] = max(maxn[2], dp[j]+j1);
				maxn[3] = max(maxn[3], dp[j]-j1);
			}
			//cout<<"ans: "<<ans<<endl;
			//cout<<"maxn: "; for (int i=0; i<4; ++i) cout<<maxn[i]<<' '; cout<<endl;
		}
		printf("%lld\n", ans);
	}
}

signed main()
{
	#ifdef DEBUG
	freopen("1.in", "r", stdin);
	#endif
	
	n=read(); m=read();
	task::solve();

	return 0;
}

标签:biology,int,题解,复杂度,long,spfa,dp,define
来源: https://www.cnblogs.com/narration/p/14999299.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有