首页 > 其他分享 >P3671 [USACO17OPEN] Where's Bessie? S 题解

P3671 [USACO17OPEN] Where's Bessie? S 题解

时间:2024-03-02 17:13:50浏览次数:18  
标签:ft mat int 题解 矩阵 dfs && USACO17OPEN Bessie

我们先枚举所有子矩阵,验证其在不考虑重叠的情况下是否为 PCL 矩阵(dfs 求一遍联通块即可)。

然后将所有满足条件的矩阵存下来,最后朴素判断每个矩阵是否被其他矩阵包括,若没有矩阵包括它,则其对于答案的贡献为 \(1\),累加所有贡献即为最终结果。

时间复杂度是 \(O(n^6)\) 的。

思路很简单,讲一下坑点:

  • dfs 求联通块时,注意坐标范围不是 \(1 \sim n\) 而是当前子矩阵的左上角坐标 \(\sim\) 右下角坐标。

  • 枚举子矩阵时,左下角坐标可以等于右下角坐标,所以注意循环变量的初始值设定。

代码(略有压行):

#include<bits/stdc++.h>
#define int long long
#define ft first
#define sc second
using namespace std;
int n,ans,tot,dx[]={0,0,-1,1},dy[]={-1,1,0,0};
char mp[31][31];
bool fl[31][31]; //标记联通块
pair<pair<int,int>,pair<int,int> > mat[160031]; //存放合法矩阵
void dfs(int x,int y,int n1,int n2,int m1,int m2,char c){ //dfs 求联通块
    fl[x][y]=1;
    for(int i=0;i<4;i++){
        int xx=x+dx[i],yy=y+dy[i];
        if(xx>=n1&&xx<=n2&&yy>=m1&&yy<=m2&&!fl[xx][yy]&&mp[xx][yy]==c) dfs(xx,yy,n1,n2,m1,m2,c);
    }
}
bool check(int x,int y,int xx,int yy){ //校验矩阵
    char c1=' ',c2=' '; int cnt1=0,cnt2=0; //分别表示:两种不同类型的字符、两种字符的联通块数量
    for(int i=x;i<=xx;i++){ for(int j=y;j<=yy;j++){ if(c1==' '){ c1=mp[i][j]; break; } } } //找出第一种字符
    for(int i=x;i<=xx;i++){ for(int j=y;j<=yy;j++){ if(c2==' '&&mp[i][j]!=c1){ c2=mp[i][j]; break; } } } //找出第二种字符
    for(int i=x;i<=xx;i++) for(int j=y;j<=yy;j++) if(mp[i][j]!=c1&&mp[i][j]!=c2) return 0; //若字符种类超过两种一定不合法
    memset(fl,0,sizeof(fl));
    for(int i=x;i<=xx;i++) for(int j=y;j<=yy;j++)
            if(mp[i][j]==c1&&!fl[i][j]) cnt1++,dfs(i,j,x,xx,y,yy,c1); //求第一种字符的联通块数量
    for(int i=x;i<=xx;i++) for(int j=y;j<=yy;j++)
            if(mp[i][j]==c2&&!fl[i][j]) cnt2++,dfs(i,j,x,xx,y,yy,c2); //求第二种字符的联通块数量
    if((cnt1==1&&cnt2>1)||(cnt1>1&&cnt2==1)) return 1; return 0; //若一种字符的联通块数量>1且另一种=1则合法,否则不合法
}

signed main(){
	ios::sync_with_stdio(0);
	cin>>n;
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>mp[i][j];
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
	       for(int ii=i;ii<=n;ii++) for(int jj=j;jj<=n;jj++)
	               if(check(i,j,ii,jj)) mat[++tot].ft.ft=i,mat[tot].ft.sc=j,mat[tot].sc.ft=ii,mat[tot].sc.sc=jj; //存放矩阵
	for(int i=1;i<=tot;i++){
	    bool f=1;
	    for(int j=1;j<=tot;j++) if(i!=j&&mat[i].ft.ft>=mat[j].ft.ft&&mat[i].ft.sc>=mat[j].ft.sc&&mat[i].sc.ft<=mat[j].sc.ft&&mat[i].sc.sc<=mat[j].sc.sc){ f=0; break; } //遍历矩阵判断是否覆盖
	    if(f) ans++; //累加贡献
	}
	cout<<ans;
    return 0;
}

标签:ft,mat,int,题解,矩阵,dfs,&&,USACO17OPEN,Bessie
From: https://www.cnblogs.com/XOF-0-0/p/18048892

相关文章

  • P1874 快速求和 题解
    updon2023/12/22:修改了代码,现已通过所有hack数据。首先定义状态:令\(dp_{i,j}\)表示前\(i\)个数字要变成\(j\)所需要的最少加号个数。同时,我们还需要一个辅助数组:令\(num_{i,j}\)表示\(i\simj\)的数字组成的数(不添加加号)。然后进行转移。显然可以枚举......
  • AT_dp_z Frog 3 题解
    这题的朴素dp是显然的。令\(dp_i\)表示跳到第\(i\)个石头的最小花费,有转移方程:\[dp_i=\min_{j=1}^{i-1}\{dp_j+(h_i-h_j)^2+C\}\]直接转移是\(O(n^2)\)的,考虑优化。首先对于\(\min\)以内的式子化简,得:\[dp_j+h_i^2+h_j^2-2h_ih_j+C\]将与\(j\)无关的项剔除,得:\[d......
  • 喵了个喵 题解
    传送门这玩意是T2???观察到\(k=2n-2\)或\(k=2n-1\),所以我们可以尝试让每个栈里面都保持两张牌。同时保留一个空栈,用来消栈底。记这个保留的空栈为\(sp\)。策略1:如果当前牌堆顶的牌能消,必然消;否则除了\(sp\),如果存在一个没有填到两张牌的栈,放进去。当\(k=2n-1\)......
  • CF1915D Unnatural Language Processing 题解
    容易发现音节的划分不仅要求子串形如\(\texttt{CV}\)或\(\texttt{CVC}\),并且接下来的两个字符也必须是\(\texttt{CV}\),不然会导致无法划分下去。于是我们遍历字符串,找出所有满足上述条件的子串,记录需要输出\(\texttt{.}\)的位置即可。实现:intn;strings,ans,t="";cin>......
  • CF1915E Romantic Glasses 题解
    我们考虑维护\(sum_i\)表示前\(i\)个数中偶数下标的数之和与奇数下标的数之和之差,其中\(sum_0=0\)。若在某一时刻,有\(sum_i=sum_j(j<i)\),说明\(j\simi\)中偶数下标的数之和与奇数下标的数之和之差为\(0\)。这个使用map判断即可。实现:intn,f=0;cin>>n;m.clear()......
  • CF1921D Very Different Array 题解
    补充一个对本题贪心思路更(?)清楚的解释。本题贪心思路:在\(a_i,b_i\)分别升序的情况下,对于每个\(a_i\),与它差值最大的\(b_i\)只可能出现在\(b_{n-i+1}\)与\(b_{m-i+1}\)这两者中。证明:首先,假设我们有一个长度为\(n\)的升序序列\(s\)。则对于\(s_1\),与它差值最大......
  • CF10E 题解
    传送门有\(n\)种货币。找一个最小的金额\(x\),使得贪心法付款不是最优解;如果贪心法始终都是最优解,输出\(-1\)。\((n\le400)\)将货币集合记作一个\(n\)维向量\(C=(c_1,c_2,\dots,c_n)\)。对于金额\(x\)的一个表示法,也记作一个\(n\)维向量\(V\)。即\(C\timesV=x\)。......
  • NOIP2023 T4 题解
    T4写出转移方程:\(f_i\)表示前\(i\)天且第\(i\)天必须跑的最大能量值。\(g_i=\max\limits_{j=1}^i\{f_j\}\)。初值\(f_0=g_0=0\)。对于转移方程,考虑枚举最后一段跑的段是从哪里开始的:\(f_i=\displaystyle\max_{j=i-k+1}^i(g_{j-2}+prize(j,i)-(j-i+1)\timesd)\)。其中\(p......
  • SP14846 GCJ1C09C - Bribe the Prisoners 题解
    非常好区间dp。我们发现直接依题做是困难的,因此考虑反着做。也即,假定起初那\(Q\)个牢房均为空,现在要将给定的\(Q\)的犯人插入其中,求最小代价。然后我们发现这题和P1775很像,相当于每插入一个人,两段不相邻的牢房就被合并到了一起。接着我们就考虑这玩意怎么做区间dp。......
  • 【题解】「HDU 7084」Pty loves string
    CQBZOJHDU7084不难想到把最终在\(S\)从中间分开,就变成了前后两个broder拼起来。考场重现:直接把所有的broder求出来,将相同长度的broder的下标存在一起,然后暴力匹配,最后还没来及优化。考场代码(除了fail树,其她其实都挺逼近正解正解是建出fail树(甚至搞忘还有这东......