Cheating Gomoku Narabe(atcoder.jp)

原题再现

(全英无翻译)D - Cheating Gomoku Narabe (atcoder.jp)icon-default.png?t=N7T8https://atcoder.jp/contests/abc337/tasks/abc337_d


       解释题意

        大概题意:给出一个H*W的矩阵,叫你求出把矩阵中的H行W列中o的数量>=k的修改o的次数,我们可以把.改成o求操作次数最少的

        例:

        #1

        #2

                        

        #3

 

  


       正片开始

        OK,那我们先构建一个S[ ][ ]来储存我们的输入,但是题目并没有给出H,W的大小,只给出了:H×W≤2×10^5,不排除极限情况(H=2*10^5,W=1)我们定一个S[2*1e5][2*1e5]的数组,除非你的运行空间超大,不然肯定爆😅,此时肯定就有小伙伴要说:先开个string s[2*1e5]不就OK了

        于是1.0暴力版本新鲜出炉:


#include <bits/stdc++.h>
using namespace std;
int h, w, k;
string s[20020], b1[200020], b2[200020];
int ans1 = 0x3f3f3f3f, ans2 = 0x3f3f3f3f;
void qz() {
	for (int i = 0; i < w; i++)//b1->得到s[]的列
		for (int j = 0; j < h; j++)
			b1[i][j] = s[j][i];
	for (int i = 0; i < h; i++)//b2->得到s[]的行
		for (int j = 0; j < w; j++)
			b2[i][j] = s[i][j];
}
int main() {
	cin >> h >> w >> k;
	for (int i = 0; i < h; i++)//输入
		cin >> s[i];
	qz();//获得s[]的行与列
	for (int i = 0; i < w; i++) {
		int sx = 0, so = 0;
		for (int j = 0; j < h; j++) {
			if (b1[i][j] == 'x') sx++;//如果b1[i][j]==x,x的出现次数增加
			if (b1[i][j] == 'o') so++;//如果b1[i][j]==o,o的出现次数增加
		}
		if (so >= k) cout << 0, exit(0);	//如果o出现次数本来就>=k输出0,结束程序(exit(0))
		else if (sx + so == w) continue;	//如果o出现次数+x出现次数==w,无法修改,continue
		else if (w - sx < k) continue;		//w-如果x出现次数<k,无法修改,continue
		else ans1 = min(ans1, k - so);		//取我们要修改的值的最小值
	}
	for (int i = 0; i < h; i++) {//同b1
		int sx = 0, so = 0;
		for (int j = 0; j < w; j++) {
			if (b2[i][j] == 'x') sx++;
			if (b2[i][j] == 'o') so++;
		}
		if (so >= k) cout << 0, exit(0);
		else if (so + sx == h) continue;
		else if (w - sx < k) continue;
		else ans2 = min(ans2, k - so);
	}
	min(ans1, ans2) != 0x3f3f3f3f ? cout << min(ans1, ans2) : cout << -1;
	/*
	相当于:if(min(ans1,ans2)!=0x3f3f3f3f)
				cout<<min(ans1,ans2);
			else
				cout<<-1;
	*/
	return 0;
}

        然后你就会发现错了4个点

        好,接下来展开优化:滑动窗口(不懂得看这:滑动窗口详解_窗口滑动-CSDN博客

        于是,我们可以开始魔法:

        

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define endl "\n"
using namespace std;
int n, m, k;
int sx, so;
const int N = 1e7;
string s[N];
int ans = inf;
int main() {
	cin >> n >> m >> k;
	for (int i = 0; i < n; i++) {
		cin >> s[i];
	}
	
		for (int i = 0; i < n; i++) {
			sx = so = 0;
			for (int j = 0; j < k; j++) {
				if (s[i][j] == 'x') sx++;
				if (s[i][j] == 'o') so++;
			}
			if (sx == 0) ans = min(ans, k - so);
			for (int j = k; j < m; j++) {
				if (s[i][j - k] == 'x') sx--;
				if (s[i][j - k] == 'o') so--;
				if (s[i][j] == 'x') sx++;
				if (s[i][j] == 'o') so++;
				if (sx == 0) ans = min(ans, k - so);
			}
		}
	
		for (int i = 0; i < m; i++) {
			sx = so = 0;
			for (int j = 0; j < k; j++) {
				if (s[j][i] == 'x') sx++;
				if (s[j][i] == 'o') so++;
			}
			if (sx == 0) ans = min(ans, k - so);
			for (int j = k; j < n; j++) {
				if (s[j - k][i] == 'x') sx--;
				if (s[j - k][i] == 'o') so--;
				if (s[j][i] == 'x') sx++;
				if (s[j][i] == 'o') so++;
				if (sx == 0) ans = min(ans, k - so);
			}
		}
	ans != inf ? cout << ans : cout << -1;
	return 0;
}

        然后当你激动的测完样例提交时:

        

        裂了( ఠൠఠ )ノ

        哦,原来要加一个if()!!!!

        AC代码

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define endl "\n"
using namespace std;
int n, m, k;
int sx, so;
const int N = 1e7;
string s[N];
int ans = inf;
int main() {
	cin >> n >> m >> k;
	for (int i = 0; i < n; i++) {
		cin >> s[i];
	}
	if (m >= k)//对,要判断,不然卡死循!!!
		for (int i = 0; i < n; i++) {
			sx = so = 0;
			for (int j = 0; j < k; j++) {
				if (s[i][j] == 'x') sx++;
				if (s[i][j] == 'o') so++;
			}
			if (sx == 0) ans = min(ans, k - so);
			for (int j = k; j < m; j++) {
				if (s[i][j - k] == 'x') sx--;
				if (s[i][j - k] == 'o') so--;
				if (s[i][j] == 'x') sx++;
				if (s[i][j] == 'o') so++;
				if (sx == 0) ans = min(ans, k - so);
			}
		}
	if (n >= k)
		for (int i = 0; i < m; i++) {
			sx = so = 0;
			for (int j = 0; j < k; j++) {
				if (s[j][i] == 'x') sx++;
				if (s[j][i] == 'o') so++;
			}
			if (sx == 0) ans = min(ans, k - so);
			for (int j = k; j < n; j++) {
				if (s[j - k][i] == 'x') sx--;
				if (s[j - k][i] == 'o') so--;
				if (s[j][i] == 'x') sx++;
				if (s[j][i] == 'o') so++;
				if (sx == 0) ans = min(ans, k - so);
			}
		}
	ans != inf ? cout << ans : cout << -1;
	return 0;
}

        OK啊,感谢观看

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值