LOJ3193 「ROI 2019 Day2」机器人高尔夫球赛

Link
首先有一个比较显然的\(O(nm)\)的dp。
同时我们可以发现,对于一个洞,它只能影响到离他Manhattan距离不大于\(2\)的位置。
剩下的点就只能够从它左下方的点转移过来。
按对角线顺序dp,用map维护被洞影响到的点特殊转移即可。

#include<cctype>
#include<cstdio>
#include<vector>
#include<utility>
#include<algorithm>
#include<unordered_map>
using i64=long long;
using pi=std::pair<int,int>;
const int P=998244353;
char ibuf[1<<22],*iS=ibuf;
int ans;std::vector<pi>vec;std::unordered_map<i64,int>val;std::unordered_map<int,int>f,g;
int read(){int x=0,f=1;while(isspace(*iS))++iS;if(*iS=='-')f=-1,++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return f*x;}
int dp(int x,int y){return f.count(x-y)? f[x-y]:0;}
i64 hash(int x,int y){return x*10000000000ll+y;}
void solve(int o)
{
    f.clear(),g.clear();
    for(auto[x,y]:vec)
    {
	if(f.count(x-y)&&((x+y)&1)==o) ans=(ans+1ll*f[x-y]*(g[x-y]-x))%P;
	if(val.count(hash(x,y))) f[x-y]=val[hash(x,y)];
	else if(((x+y)&1)==o) f[x-y]=std::min(dp(x+1,y),dp(x,y+1));
	else f[x-y]=std::max(dp(x+1,y),dp(x,y+1));
	g[x-y]=x;
    }
    for(auto it:f)
    {
	int x=g[it.first],y=x-it.first;
	if(((x+y)&1)==o) ans=(ans+1ll*it.second*std::min(x,y))%P;
    }
}
int main()
{
    fread(ibuf,1,1<<22,stdin);
    read(),read();int k=read();
    while(k--)
    {
	int x=read(),y=read();val[hash(x,y)]=read();
	for(int i=0;i<=2;++i) for(int j=0;i+j<=2;++j) if(x>i&&y>j) vec.emplace_back(x-i,y-j);
    }
    std::sort(vec.begin(),vec.end()),vec.erase(std::unique(vec.begin(),vec.end()),vec.end()),std::reverse(vec.begin(),vec.end());
    solve(0),solve(1),printf("%d",(ans+P)%P);
}
posted @ 2020-06-11 07:16  Shiina_Mashiro  阅读(340)  评论(0编辑  收藏  举报