[USACO 2020 Open Platinum]Sprinklers 2: Return of the Alfalfa
Posted youddjxd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[USACO 2020 Open Platinum]Sprinklers 2: Return of the Alfalfa相关的知识,希望对你有一定的参考价值。
Description
Farmer John 有一块小的田地,形状为一个 (N) 行 (N) 列的一个方阵,对于所有的 (1 le i,j le N),从上往下的第 (i) 行的从左往右第 (j) 个方格记为 ((i,j))。他有兴趣在他的田地里种植甜玉米和苜蓿。为此,他需要安装一些特殊的洒水器。
在方格 ((I,J)) 中的甜玉米洒水器可以喷洒到所有左下方的方格:即满足 (I le i) 以及 (j le J) 的 ((i,j))。
在方格 ((I,J)) 中的苜蓿洒水器可以喷洒到所有右上方的方格:即满足 (i le I) 以及 (J le j) 的 ((i,j))。
被一个或多个甜玉米洒水器喷洒到的方格可以长出甜玉米;被一个或多个苜蓿洒水器喷洒到的方格可以长出苜蓿。但是被两种洒水器均喷洒到(或均喷洒不到)的方格什么也长不出来。
帮助 Farmer John 求出在他的田地里安装洒水器的方案数((mod 10^9 + 7)),每个方格至多安装一个洒水器,使得每个方格均能生长作物(即被恰好一种洒水器喷洒到)。
某些方格正被长毛奶牛占据;这不会阻止这些方格生长作物,但是这些方格里不能安装洒水器。
Solution
显然最后的状态会是中间有一条折线,左边是一种喷水器,右边是另一种,每个拐角处都必须安装,而其他地方随便安装(且种类确定)
设状态(dp[i][j])代表喷左下的喷水器的最右下的一个在((i,j))的方案数目(这个方案数目不包含右下角所填方案数,因为一会儿还要再往下转移),而(s[i][j])代表((i,j))右下方(包括i行和j列)一共有多少个可以填的地方
那么答案显然就是(sum dp[i][j] imes (s[i][j+1] - [j!=n]) imes [mapn[n][j+1]==1])
那考虑怎么转移,显然每个(dp[i][j])都可以从(dp[k][l](k<i,l<j))转移来
设上一个喷水器在((k,l))(即深红色块,而浅红色块是((i,j))),那么对于图示这一块灰色地区,是可以任意填的,
(图片来自洛谷题解,用户为水印所示)
所以得到一个很棒的转移:
(dp[i][j]=sum dp[k][l] imes 2^{s[k][l+1]-s[i][j+1]-1-[i>1]} imes [mapn[i-1][l+1]==1])
其中的细节一是特判边界是否要填另一种洒水器,二是判断假如要填的话能不能填上
然后转化一下:
(dp[i][j]=sum (dp[k][l] imes {2^s[k][l+1]} imes [mapn[i-1][l+1]==1]) imes 2^{-s[i][j+1]-1-[i>1]})
那么显然前面那个东西可以二维前缀和一下:
(pre[i-1][l]=sum (dp[1~i-1][l] imes 2^{s[1~i-1][l+1]}) imes [mapn[i-1][l+1]==1])
(pre2=pre[i-1][1~j-1])
然后就可以快乐(O(n^2))转移了,代码是很水的,就是边界特判有点烦
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
int n;
int poww[4000010];
int ipow[4000010];
char ch[2010];
bool mapn[2010][2010];
int s[2010][2010];
int pre[2010];
int dp[2010][2010];
signed main(){
scanf("%lld",&n);
poww[0]=ipow[0]=1;
for(int i=1;i<=n*n;++i)poww[i]=2*poww[i-1]%mod,ipow[i]=(mod/2+1)*ipow[i-1]%mod;
for(int i=1;i<=n;++i){
scanf("%s",ch+1);
for(int j=1;j<=n;++j){
mapn[i][j]=(ch[j]==‘.‘);
}
}
for(int i=1;i<=n;++i)mapn[0][i]=1;
for(int i=n;i>=0;--i){
for(int j=n;j>=0;--j){
s[i][j]=s[i][j+1]+s[i+1][j]-s[i+1][j+1]+mapn[i][j];
}
}
dp[0][0]=1;
pre[0]=poww[s[1][1]];
for(int i=1;i<=n;++i){
int pre2=0;
for(int j=1;j<=n;++j){
pre2=(pre2+(pre[j-1]*mapn[i-1][j])%mod)%mod;
if(!mapn[i][j])continue;
dp[i][j]=(pre2*ipow[s[i][j+1]+1+(i>1)])%mod;
}
for(int j=1;j<=n;++j)pre[j]=(pre[j]+(dp[i][j]*poww[s[i][j+1]])%mod);
}
int ans=0;
for(int i=0;i<n;++i){
ans=(ans+((pre[i]*mapn[n][i+1])%mod*ipow[1])%mod)%mod;
}
ans=(ans+pre[n])%mod;
printf("%lld
",ans);
}
以上是关于[USACO 2020 Open Platinum]Sprinklers 2: Return of the Alfalfa的主要内容,如果未能解决你的问题,请参考以下文章
[USACO 2020 Open Platinum]Sprinklers 2: Return of the Alfalfa
「USACO 2021 US Open Platinum」Balanced Subsets
「USACO 2021 US Open Platinum」United Cows of Farmer John
题解 loj3265 3266 3267 USACO 2020.2 Platinum(全)
USACO2020JAN Platinum T2 官方正解的翻译?
USACO 2020 January Contest, Platinum Problem 1. Cave Paintings