2022 CSP-S T1求助,T了两个点
查看原帖
2022 CSP-S T1求助,T了两个点
820348
smyoking楼主2023/10/25 13:15
#include<bits/stdc++.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>

#define int long long

using namespace std;

inline int read() {
	int x=0,f=1;char s=getchar();
	while (s>'9'||s<'0') {
		if (s=='-') f=-f;
		s=getchar();
	}
	while (s>='0'&&s<='9') {
		x=(x<<1)+(x<<3)+(s^48);
		s=getchar();
	}
	return x*f;
}

const int  N = 1010;
const int mod = 998244353;

int T,id,n,m,vc,vf,mmap[N][N],ctot,ftot;
int hmax[N][N],lmax[N][N];
char k;

void IN() {//输入图+预处理
    for (int i=1;i<=n;++i) {  
        for (int j=1;j<=m;++j) {
            cin>>k;
            if (k=='1') mmap[i][j]=1;
        	else mmap[i][j]=0;
		}
    }
    //预处理出hmax和lmax
    //hmax表示这个点可以到达的最右端的点,路径上的数字全为0
    //同理,lmax表示可以到达的最下端的点
    for (int i=1;i<=n;++i) {  
        if (mmap[i][m]==0) hmax[i][m]=m; 
            for (int j=m-1;j>=1;--j) {
            if (mmap[i][j]==1) continue;
            if (mmap[i][j+1]==1) hmax[i][j]=j;
            else hmax[i][j]=hmax[i][j+1];
        }
    }
    for (int i=1;i<=m;++i) {
        if (mmap[n][i]==0) lmax[n][i]=n;
        for (int j=n-1;j>=1;--j) {
            if (mmap[j][i]==1) continue;
            if (mmap[j+1][i]==1) lmax[j][i]=j;
            else lmax[j][i]=lmax[j+1][i]; 
        }
    }
}

int yy(int a1,int a2,int b1,int b2) {  //计算可以构成的c的情况
    int p1=hmax[a1][a2]-a2;
    int p2=hmax[b1][b2]-b2;
    return p1*p2%mod;
}

void solve() {
    for (int i=1;i+1<n;++i) {
        for (int j=1;j<m;++j) {
            if (mmap[i][j]==1) continue;//这个点不能种花
            if (mmap[i][j+1]==1) continue;//相邻右边的点不能种花,相当于C上端的横线无法拓展出去
            if (mmap[i+1][j]==1) continue;//同上
            for (int k=i+2;k<=n;++k) {
                if (mmap[k][j]==1) break;//遇到了土坑,无法向下拓展了
                if (mmap[k][j+1]==1) continue; //C下面的横线无法向右拓展
                //printf("%d,%d->%d,%d\n",i,j,k,j);
                int p=yy(i,j,k,j);
                ctot=(ctot+p)%mod;
                if (k+1<=n&&mmap[k+1][j]==0) ftot=(ftot+p*(lmax[k][j]-k)%mod)%mod;  
                //相当于在C的基础上往下端拓展得到F
            }
        }
    }
}

signed main(){
    //freopen("random.txt","r",stdin);
    //freopen("wa.txt","w",stdout);
    T=read();id=read();
    while (T--) {
        n=read();m=read();vc=read();vf=read();
        //memset(hmax,0,sizeof(hmax));
        //memset(lmax,0,sizeof(lmax));
        //memset(mmap,0,sizeof(mmap));
        ctot=0;ftot=0;//初始化
        //ctot ftot 分别记录可以构成C和F的总数
        IN();    
        solve();
        printf("%lld %lld\n",ctot*vc,ftot*vf);
    }
    return 0;
}
2023/10/25 13:15
加载中...