• P7532 [USACO21OPEN] Balanced Subsets P 题解


    P7532 [USACO21OPEN] Balanced Subsets P

    sol

    我们先解读一下题目中给的限制条件,就是一个凸多边形的形状

    IcrQ1I.md.png

    单考虑左右边界,发现是先增后减,或者一直往一个方向走

    那么我们可以写一个 \(o(n^5)\) 的 DP ,定义 \(F[i][a][b][l(0/1)][r(0/1)]\) 表示
    枚举到第 \(i\) 行,现在的左边界是 \(a\),右边界是 \(b\)\(l,r\)表示左右边界是否递增,\(0\) 表示增, \(1\)表示减

    然后考虑转移

    if(x>=l&&y<=r)f[i][l][r][0][0]+=f[i-1][x][y][0][0];
    if(x>=l&&x<=r&&y>r)f[i][l][r][0][1]+=f[i-1][x][y][0][0];
    if(x>=l&&x<=r&&y>=r)f[i][l][r][0][1]+=f[i-1][x][y][0][1];
    if(y>=l&&y<=r&&x<l)f[i][l][r][1][0]+=f[i-1][x][y][0][0];
    if(y>=l&&y<=r&&x<=l)f[i][l][r][1][0]+=f[i-1][x][y][1][0];
    if(x<=l&&y>=r)f[i][l][r][1][1]+=f[i-1][x][y][1][1];
    if(x<l&&y>=r)f[i][l][r][1][1]+=f[i-1][x][y][0][1];
    if(x<=l&&y>r)f[i][l][r][1][1]+=f[i-1][x][y][1][0];
    if(x<l&&y>r)f[i][l][r][1][1]+=f[i-1][x][y][0][0];
    

    考虑怎么优化

    我们发现,一种情况 \(l,r\) 要转移到 \(l',r'\) 在每种 \(0/1\) 状态下都是满足某种关系,那么我们可不可以将他们记录下来呢

    答案是可以的

    \(l,r,l',r'\) 看成 二维平面中的一个点, \(l,r\) 分别对应两个坐标,那么满足条件的 \(l',r'\) 是二维平面中的一些矩阵区域

    Ics1PJ.png

    如图,当 \(0,0\) 状态,也就是两边都要递增是,要满足 \(l'<l,r'<r\) 也就是图中区域

    然后用二维前缀和处理就好了

    code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn=155;
    const LL TT=1e9+7;
    int N,s[maxn];
    LL f[maxn][maxn][maxn][2][2],g[maxn][maxn][maxn][2][2];
    char ch[maxn];
    LL ans=0;
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    int get(int i,int x,int y,int p,int q,int l,int r){
    	return (((g[i][y][q][l][r]-g[i][x-1][q][l][r])%TT-g[i][y][p-1][l][r])%TT+g[i][x-1][p-1][l][r]+TT)%TT;
    }
    int main(){
    	N=read();
    	for(int i=1;i<=N;i++){
    		scanf("%s",ch+1);
    		for(int j=1;j<=N;j++) s[j]=s[j-1]+(ch[j]=='G');
    		for(int l=N;l>=1;l--)
    		for(int r=l;r<=N;r++)if(s[r]-s[l-1]==r-l+1){
    			f[i][l][r][0][0]=1+get(i-1,l,r,l,r,0,0);
    			f[i][l][r][0][1]=(get(i-1,l,r,r+1,N,0,0)+get(i-1,l,r,r,N,0,1))%TT;
    			f[i][l][r][1][0]=(get(i-1,1,l-1,l,r,0,0)+get(i-1,1,l,l,r,1,0))%TT;
    			f[i][l][r][1][1]=((get(i-1,1,l,r,N,1,1)+get(i-1,1,l-1,r+1,N,0,0))%TT+(get(i-1,1,l-1,r,N,0,1)+get(i-1,1,l,r+1,N,1,0))%TT)%TT;
    			for(int ii=0;ii<=1;ii++)
    			for(int jj=0;jj<=1;jj++)ans=(ans+f[i][l][r][ii][jj])%TT;
    		}
    		for(int p=0;p<=1;p++)
    		for(int q=0;q<=1;q++)
    		for(int x=1;x<=N;x++)
    		for(int y=1;y<=N;y++)
    			g[i][x][y][p][q]=(((g[i][x-1][y][p][q]+g[i][x][y-1][p][q])%TT-g[i][x-1][y-1][p][q])%TT+f[i][x][y][p][q])%TT;
    	}
    	printf("%lld\n",(ans+TT)%TT);
    	return 0;
    }
    
    
  • 相关阅读:
    【git】强制覆盖本地代码(与git远程仓库保持一致)
    ffmpeg CLI常用命令
    旧机改造步骤
    macbook air 2012 mid 安装 windows10 双系统遇到错误 no bootable device insert boot disk and press any key
    window、Linux 文本文件转换
    phalcon bug: model的findFirst会自动忽略一些空格
    oss2罗列所有文件
    如何让linux的history命令显示时间记录
    nginx 常用配置
    shell脚本 切换用户
  • 原文地址:https://www.cnblogs.com/martian148/p/15553302.html
Copyright © 2020-2023  润新知