Rise in Price | HDU 6981 给定一个
n
×
n
n\times n
n×n 的网格 位置
(
i
,
j
)
(i,j)
(i,j) 上有权值
a
i
,
j
a_{i,j}
ai,j 与
b
i
,
j
b_{i,j}
bi,j 从左上角走到右下角,每次可以向下走一格 / 向右走一格 但不能走出网格 你走到一个位置,就能获得
a
+
=
a
i
,
j
a+=a_{i,j}
a+=ai,j ,
b
+
=
b
i
,
j
b+=b_{i,j}
b+=bi,j 你最后的收益就是
∑
a
×
∑
b
\sum_{a} \times \sum_{b}
∑a×∑b 求这个收益最大是多少
1
≤
n
≤
100
1\le n\le 100
1≤n≤100 并且满足
a
i
,
j
,
b
i
,
j
a_{i,j},b_{i,j}
ai,j,bi,j随机均匀分布在
[
1
,
1
0
6
]
[1,10^6]
[1,106] 中
思路
一开始怎么搞都不是很好搞,这个随机均匀分布的条件也没有用到过,模拟退火也不行 各种贪心方法也都是
W
r
o
n
g
A
n
s
w
e
r
\color{red}{Wrong\ Answer}
WrongAnswer 仔细看,
n
2
=
1
0
4
n^2=10^4
n2=104,明显时间有很大的余地 我们能不能多存一些有用的状态呢?
我们设一个结构体
n
o
d
e
{
a
,
b
,
a
b
}
node\{a,b,ab\}
node{a,b,ab} 表示从起点到某个点的
∑
a
,
∑
b
,
∑
a
×
∑
b
\sum_a,\sum_b,\sum_a\times\sum_b
∑a,∑b,∑a×∑b 根据贪心策略,我们优先 存储
∑
a
×
∑
b
\sum_a\times\sum_b
∑a×∑b 较大的,其他的排序规则其实是无所谓的(因为数据是随机均匀分布的) 我们每个点设置一个存储上限
k
k
k 然后时间复杂度约乎为
O
(
n
2
k
log
k
)
O(n^2k\log k)
O(n2klogk) 因为用
v
e
c
t
o
r
vector
vector 去存,特别慢 我这里
k
=
50
k=50
k=50 就可以通过了
代码
T
i
m
e
s
:
280
M
s
Times:280Ms
Times:280Ms
#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedeflonglong ll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =1e2+50;constint MOD =1e9+7;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;
ll aa[MAX][MAX],bb[MAX][MAX];structnode{
ll a,b,ab;
bool operator <(const node &ND)const{if(ab != ND.ab)return ab > ND.ab;if(abs(a-b)!=abs(ND.a-ND.b))returnabs(a-b)<abs(ND.a-ND.b);return a < ND.a;}};constint k =50;
vector<node>V[MAX][MAX];intmain(){
IOS;int T;cin >> T;while(T--){int n;cin >> n;for(int i =0;i <= n;++i)for(int j =0;j <= n;++j)
V[i][j].clear();for(int i =1;i <= n;++i)for(int j =1;j <= n;++j)
cin >> aa[i][j];for(int i =1;i <= n;++i)for(int j =1;j <= n;++j)
cin >> bb[i][j];
V[0][1].push_back((node){0,0,0});for(int i =1;i <= n;++i)for(int j =1;j <= n;++j){for(auto it : V[i-1][j]){
ll t1 = it.a + aa[i][j];
ll t2 = it.b + bb[i][j];
V[i][j].push_back((node){t1,t2,t1*t2});}for(auto it : V[i][j-1]){
ll t1 = it.a + aa[i][j];
ll t2 = it.b + bb[i][j];
V[i][j].push_back((node){t1,t2,t1*t2});}sort(V[i][j].begin(),V[i][j].end());int sz = V[i][j].size();while(sz > k){
sz--;
V[i][j].pop_back();}}
ll ans =0;for(auto it : V[n][n]){
ans =max(ans,it.ab);}
cout << ans << endl;}return0;}