Codeforces Round #639 (Div. 2)
(這場官方搞事,唉,just solve for fun...)
A找規律
給定n*m個拼圖塊,每個拼圖塊三凸一凹,問能不能拼成 n * m的長方形
只要有某一維為1都可,只要無一維為1,只能是 2 * 2
B找規律,二分
搭金字塔
如圖:
給定n,每次儘可能搭高的,問能搭幾個金字塔
找規律,預處理,查詢時二分
C數學,桶
換房子,下面就是換的規則(無非就是新房為k+Ak再對n取模)
模擬一下,桶存即可
D深搜
規則很多很複雜
原題地址:
https://codeforces.ml/contest/1345/problem/D
主要的構造要求
思路:整理一下所有題目背景,發現我們為了滿足規則2,不妨先在所有黑格子上放S即可,然後再考慮如何放N,這樣很輕易實現規則2
先講一下針對規則3非法情況
所有的黑格子形成的區域塊一定是一個凸塊
如果是凹塊(包括中空和邊緣缺失的情況)一定會破壞規則3
因為資料比較小,所以我們暴力去查是否滿足凸塊,即一旦一行或者一列出現了黑塊,那麼這個黑塊只能連續,否則肯定非法
再考慮一下規則1如何非法
根據前面的邏輯,我們S只放在黑色塊上,那麼只要一行或一列全為白,那就破壞了規則1
但真的是這樣嗎?
這裡真的很坑,按照前面的思路,我們只是將所有黑格上放S,不意味著白格不能放S
如果說一行全白並且一列全白,那麼他們的交點如果我放S,那麼規則1就不會被破壞了
所以這一點一定要注意,否則很多可行解會被遺漏
一旦滿足了所有要求,那麼我們最少應該放多少S嘞?
顯然一個凸塊給一個S,讓S該凸塊縱情遨遊即可
所以dfs深搜,記錄訪問情況即可
AC:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 1005
#define minn -105
#define ll long long int
#define ull unsigned long long int
#define uint unsigned int
inline int read()
{
int ans=0;
char last=' ',ch=getchar();
while(ch<'0'|ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
char a[maxn][maxn];
bool been[maxn][maxn];
int n,m;
bool ok=0;
void dfs(int x,int y)
{
if(x<1||y<1||x>n||y>m||a[x][y]=='.'||been[x][y])return;
been[x][y]=1;
dfs(x+1,y);
dfs(x-1,y);
dfs(x,y+1);
dfs(x,y-1);
}
int main()
{
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
been[i][j]=0;
n=read(),m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
}
bool check1=0,check2=0;
int k=0;
for(int i=1;i<=n;i++)
{
if(ok)break;
check2=0;
for(int j=1;j<=m;j++)
{
if(a[i][j]=='.'||ok)continue;
if(check2)ok=1;
check2=1;
while(j<=m&&a[i][j]=='#')j++;
}
if(!check2)check1=1;
}
bool check3=0,check4=0;
for(int i=1;i<=m;i++)
{
if(ok)break;
check4=0;
for(int j=1;j<=n;j++)
{
if(a[j][i]=='.'||ok)continue;
if(check4)ok=1;
check4=1;
while(j<=n&&a[j][i]=='#')j++;
}
if(!check4)check3=1;
}
if(check3!=check1)ok=1;
if(ok)
{
cout<<-1<<endl;
return 0;
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(ok)break;
if(been[i][j]||a[i][j]=='.')continue;
ans++;
dfs(i,j);
}
cout<<ans<<endl;
return 0;
}