[构造 随机] Codeforces 720C Russian Code Cup 2016 - Finals C. Homework

我是dls的脑残粉
这里写图片描述
这里写图片描述

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;

const int N=100005;

int n,m,K;
int w[N];

inline int count(){
  int ret=0;
  for (int i=0;i<n-1;i++)
    for (int j=0;j<m-1;j++){
      int x=i*m+j;
      ret+=(w[x]&w[x+m]&w[x+1])+(w[x+m+1]&w[x+m]&w[x+1])+(w[x]&w[x+m]&w[x+m+1])+(w[x]&w[x+1]&w[x+m+1]);
    }
  return ret;
}

int Q[N],l,r;
int ins[N];

const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};

inline int Jud(){
  l=r=-1;
  for (int i=0;i<n*m;i++) ins[i]=0;
  for (int i=0;i<n*m;i++) if (w[i]) { Q[++r]=i; break; }
  while (l<r){
    ++l; int x=Q[l]/m,y=Q[l]%m;
    for (int k=0;k<4;k++){
      int sx=x+dx[k],sy=y+dy[k];
      if (sx<0 || sy<0 || sx>=n || sy>=m || ins[sx*m+sy] || !w[sx*m+sy]) continue;
      Q[++r]=sx*m+sy; ins[sx*m+sy]=1;
    }
  }
  for (int i=0;i<n*m;i++) if (w[i] && !ins[i]) return 0;
  return 1;
}

inline int check(int mid){
  for (int i=0;i<n*m;i++) w[i]=(i<=mid);
  return count();
}

inline int Solve(){
  int C=4*(n-1)*(m-1);
  if (K>C) return 0;
  if (n==3 || m==3){
    if (K==C-1 || K==C-2 || K==C-4 || K==C-5) return 0;
  }else{
    if (K==C-1 || K==C-2 || K==C-4 || K==C-5 || K==C-8) return 0;
  }
  int L=-1,R=n*m,MID;
  while (L+1<R)
    if (check(MID=(L+R)>>1)>=K)
      R=MID;
    else
      L=MID;
  int cur=check(R);
  if (cur==K) return 1;
  vector<int> bl,em;
  for (int i=0;i<n*m;i++)
    if (min(i/m,abs(i/m-R/m))<=1)
      w[i]?bl.pb(i):em.pb(i);
  int x,p;
  while (cur!=K) {
    if (cur<K) {
      x=em[p=rand()%((int)em.size())];
      w[x]=1;
      if (!Jud()) { w[x]=0; continue; }
      em.erase(em.begin()+p); bl.pb(x);
      cur=count();
    }else{
      x=bl[p=rand()%((int)bl.size())];
      w[x]=0;
      if (!Jud()) { w[x]=1; continue; }
      bl.erase(bl.begin()+p); em.pb(x);
      cur=count();          
    }
  }
  return 1;
}

#define read(x) scanf("%d",&(x))
int main(){
  int T;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(T);
  while (T--){
    read(n); read(m); read(K);
    int flag=0;
    if (n<m) swap(n,m),flag=1;
    if (Solve()){
      if (!flag){
    for (int i=0;i<n;i++,putchar('\n'))
      for (int j=0;j<m;j++)
        putchar(w[i*m+j]?'*':'.');
      }else{
    for (int j=0;j<m;j++,putchar('\n'))
      for (int i=0;i<n;i++)
        putchar(w[i*m+j]?'*':'.');
      }
      putchar('\n');
    }else
      printf("-1\n\n");
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值