Maja

2023-10-20 22:59
文章标签 maja

本文主要是介绍Maja,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目

题目描述
M a j a Maja Maja和蜜蜂在一片神奇的草地上为花授粉,这块草地可以表示为一个 n ( n ≤ 100 ) n(n\le 100) n(n100) m ( m ≤ 100 ) m(m\le 100) m(m100)列的矩形,在第 i i i行第 j j j列中有 C i j ( C i j ≤ 1000000000 ) C_{ij}(C_{ij}\le 1000000000) Cij(Cij1000000000)朵没有授粉的花。

M a j a Maja Maja的蜂巢位于第 a ( 1 ≤ a ≤ n ) a(1\le a\le n) a(1an)行第 b ( 1 ≤ b ≤ n ) b(1\le b\le n) b(1bn)列,她将从她的蜂巢开始为这些花授粉,去草地上的某些块授粉,然后再返回她的蜂巢。每次操作, M a j a Maja Maja可以向相邻的上下左右中的一个方格移动,而且她永远不会离开草地。每次她经过的某块草地,都会给这块草地上所有未授粉的花授粉。但草地很神奇,一旦 M a j a Maja Maja离开草地 ( i , j ) (i,j) (i,j),所有授粉的花都会消失,新的未授粉的花又会在这片土地上生长。

由于 M a j a Maja Maja不可能永远飞行,她会在飞过 k ( 2 ≤ k ≤ 1000000000 ) k(2\le k\le 1000000000) k(2k1000000000)个格子后感到疲倦,并乐意向她的蜜蜂朋友们讲述她的冒险故事。请问,在 M a j a Maja Maja授粉并在 k k k步后返回蜂巢,她能授粉的花的数量是多少?

输出输出格式
我不想打 见标程

思路

要是你不认真想正解 也能想到就算我输 ,你可以想到一个 B F S ( BFS( BFS(或者 d p ) dp) dp)的做法——存一个位置 + + +步数的状态。没错,它是 O ( n m k ) O(nmk) O(nmk)的!相当的快呢!

好,接下来想正解:

  • 起点和终点重合的路径,一定是“原路返回”!

为什么呢?因为走到 一半(没错就是恰好一半,毕竟你要走偶数步)的时候,你有两种选择:一:原路返回;二:接着走。你来的时候走哪条,哪条路的权值就大,回去的时候就该走哪条路。

  • 路径中最多只会在两个点之间来回移动!

为什么呢?因为在 x ( x > 2 ) x(x>2) x(x>2)个点(设为 p 1 , p 2 , p 3 , . . . , p x p_1,p_2,p_3,...,p_x p1,p2,p3,...,px)之间来回移动,等同于从 p 1 p_1 p1出发走一步(走到 p 2 p_2 p2)回来 + + + p 2 p_2 p2出发走一步(走到 p 3 p_3 p3)回来 + . . . + +...+ +...+ p x − 1 p_{x-1} px1出发走一步回来。倒不如直接找 p 1 , p 2 , p 3 , . . . , p x − 1 p_1,p_2,p_3,...,p_{x-1} p1,p2,p3,...,px1中出发走一步回来的值最大的一个,不断的这么走呢。

现在,凭借上面的结论,你已经知道路径长什么样子了:在这里插入图片描述
后面那个黑坨坨表示反反复复 老不好,快用……

为什么不是中间的某一个区间反反复复,必须是头头上反反复复呢?

因为从中间反反复复,就会违背第一个结论了!

代码

#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;const int MAXN = 100,dis[][2] = {1,0,0,1,-1,0,0,-1};
const long long longInf = (1ll<<62)-1;
long long dp[2][MAXN][MAXN];// dp[s,x,y] 走2s步走到(x,y)最大的权值 
// s进行滚动,权值忽略反反复复 
int a[MAXN][MAXN];int main(){int n, m, k, x, y;scanf("%d %d %d %d %d",&n,&m,&x,&y,&k); k >>= 1;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)dp[0][i][j] = -longInf;dp[0][x-1][y-1] = 0;long long ans=0;for(int step=1; step<=k and step<n*m; ++step){for(int i=0; i<n; ++i) for(int j=0; j<m; ++j){long long tmp = -longInf, d = -longInf;for(int dir=0,tox,toy; dir<4; ++dir){tox = i+dis[dir][0]; toy = j+dis[dir][1];if(tox < 0 or tox == n or toy < 0 or toy == m)continue;tmp = max(tmp,dp[(step&1)^1][tox][toy]+a[tox][toy]);
// 走到了(tox,toy)然后又走了一步走到(i,j);a[i][j]在最后加 d = max(d,0ll+a[tox][toy]);
// 考虑最后反反复复的地方,肯定是a[i][j]+a[tox][toy] 
// 同样的,d中的a[i][j]也是最后加 }dp[step&1][i][j] = tmp+a[i][j];if(dp[step&1][i][j] < 0) continue; // 是-longInf ans = max(ans,dp[step&1][i][j]+(k-step)*(d+a[i][j]));}}printf("%lld",ans);return 0;
}

这篇关于Maja的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/250269

相关文章

【JZOJ6313】Maja【dp】

题目大意: 题目链接:https://jzoj.net/senior/#main/show/6313 一个 n × m n\times m n×m的网格图,经过点 ( x , y ) (x,y) (x,y)可以获得 a x , y a_{x,y} ax,y​的价值,一个点可以 经过多次。求从 ( x , y ) (x,y) (x,y)出发,走 p p p步后回到 ( x , y ) (x,y)

【动态规划】JZOJ_6313 Maja

题意 给出一个 n ∗ m n*m n∗m的矩阵,每个格子有些价值,走到这个格子可以获得 C i , j C_{i,j} Ci,j​点,求从起点走k步并且回到起点(a,b)的最大价值。 思路 设 f k , i , j f_{k,i,j} fk,i,j​为 k k k步时在点(i,j)获得的最大价值,40分转移显然。 可以发现一个性质,走的路是一条走过去,然后在两个点之间摩擦,再原路返回。

6313. Maja

Description 蜜蜂 Maja 到了一片草地,草地可以被描述成 N 行 M 列的网格图,在第 i 行第 j 列的位置上有 C_{i,j} 朵未授粉的花。 Maja 会从第 A 行第 B 列出发,每次只能移动到与当前位置四相邻的格子上,且不能移动到草地以外。每到达一个格子,她会把此处所有未授粉的花都授粉。 然而,当 Maja 离开一个格子,此处又会长出 C_{i,j} 朵未授粉的花。 Ma

JZOJ 6313. Maja

D e s c r i p t i o n Description Description 给定一张 n × m n\times m n×m的矩阵,第 i i i行第 j j j列的权值是 a i , j a_{i,j} ai,j​,现在要求从 ( A , B ) (A,B) (A,B)出发,走 k k k步回到原地,求最高权值和 数据范围: n , m ≤ 1 0 2 , k ≤ 1 0

UVA10182: Bee Maja (模拟)

https://vjudge.net/problem/UVA-10182   题意分析: 题意很明显,有两个蜂巢的编号方式,给出右边的,求左边的编号。 解题思路: 图中可以看出来第1层有1个,第2层有6*1=6个,第3层有6*2=12个,......第n层有6*(n-1)个。 先找出在第几层然后模拟即可。 #include <stdio.h>int px, py;void

POJ 2265 Bee Maja G++ 找规律 巧妙 背

#include <iostream>#include <cstdio>using namespace std;//英语 看博友分析 抄博友程序 找规律 巧妙 背 int main(){int a;while(cin>>a){if(a==1){cout<<0<<" "<<0<<endl;continue;}int n=0;/

POJ 2265 Bee Maja (找规律)

题目链接 题意 : 给你两个蜂巢的编号,给你一个的编号让你输出在另外一个蜂巢中对应的编号。 思路 : 先将蜂巢分层,第一层一个数,第二层6个数,第三层12个数…………然后用公式表示出第n层的最后一个数是多少,下图中竖着的是x坐标,斜着的是y坐标,往左横坐标+1,往右横坐标-1,以斜线为准往上纵坐标-1,往下纵坐标+1,(1,1)也就是18是第三圈的第一个数,(2,1)也就是20是第四圈的第一个数