CCF-CSP 39-2 水印检查(watermark)【C++】

题目

https://sim.csp.thusaac.com/contest/39/problem/1https://sim.csp.thusaac.com/contest/39/problem/1

思路参考:

80分

暴力求解,遍历所有可能的k,检验是否满足条件,可得80分

时间复杂度:O(L*n^2),粗略估计计算次数:65536*200*200*5*9

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define endl'\n'
const int N=205;
int a[N][N], t[N][N]; //白0,黑色1 

int csp[5][9]={
0,0,0,0,0,0,0,0,0,
0,1,1,0,1,1,0,1,0,
0,1,1,0,0,0,0,0,1,
0,1,1,1,1,0,0,1,1,
0,0,0,0,0,0,0,1,1
};

int n,l;

bool check()
{
	for(int i=0;i+4<n;i++)
		for(int j=0;j+8<n;j++)
		{
			int f1=1;
			for(int i1=0;i1<5;i1++)
				for(int j1=0;j1<9;j1++)
				{
					if(t[i+i1][j+j1]!=csp[i1][j1]) 
					{
						f1=0;
						break;
					}
				}
			if(f1==1) return true;
		}
	return false;
}  

void solve()
{
	cin>>n>>l;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			cin>>a[i][j];
	for(int k=1;k<l;k++)
	{
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
			{
				if(a[i][j]>=k) t[i][j]=0;//白0,黑色1 
				else t[i][j]=1; 
			}
		if(check()) cout<<k<<endl;
	}
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0);
	solve();
	return 0;
}

100分

核心思想:

对于阈值参数𝑘

  • 灰度值大于等于 k 的像素变为白色;

  • 灰度值小于 k 的像素变为黑色。

枚举左上角,每块5 x 9区域中,找对应"CSP"中白色像素位置的最小值mn作为可行解的上界,找对应"CSP"中黑色像素位置的最大值mx作为可行解的下界(取不到,因为k要大于mx),可行解为(mx,mn]

将mx+1到mn存入set(自动去重,且从大到小),最后输出即可

时间复杂度:O(n^2),粗略估计计算次数:200×200×5×9=1800000

可以再让AI总结一下代码逻辑:

在输入的 n×n 像素矩阵中,用一个固定的 5×9 二值模板 csp(0 表示白色区域,1 表示黑色区域)进行滑动匹配。

对每个可能的窗口位置:

  • 找出模板中 白色区域(0)对应位置的最小像素值mn
  • 找出模板中 黑色区域(1)对应位置的最大像素值mx

若存在整数阈值 k 满足 mx<k≤mn ,则该 k 能使当前窗口按模板正确二值化(黑区 ≥ k,白区 < k),视为可行解。

将所有窗口产生的可行 k 值加入集合 ans(自动去重并排序),最后按升序输出。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N=205;
int a[N][N];

int csp[5][9]={//白0,黑色1 
0,0,0,0,0,0,0,0,0,
0,1,1,0,1,1,0,1,0,
0,1,1,0,0,0,0,0,1,
0,1,1,1,1,0,0,1,1,
0,0,0,0,0,0,0,1,1
};

void solve()
{
	int n,l; cin>>n>>l;
	set<int>ans;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			cin>>a[i][j];
	for(int i=0;i<=n-5;i++)
		for(int j=0;j<=n-9;j++){
			int mn=0x3f3f3f3f; //白色区域的最小值 0 
			int mx=0;//黑色区域的最大值 1
			for(int x=0;x<5;x++)
				for(int y=0;y<9;y++)
				{
					if(csp[x][y]==0) mn=min(mn,a[i+x][j+y]);
					else mx=max(mx,a[i+x][j+y]);
				}
			//可行解为 (mx, mn] 
			for(int k=mx+1;k<=mn;k++)
				ans.insert(k);
		}
	for(auto k:ans) cout<<k<<endl;
		
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0);
	solve();
	return 0;
}
相关推荐
plus4s2 小时前
2月15日(78,80,81题)
c++·算法·图论
能源系统预测和优化研究2 小时前
【原创改进代码】考虑碳交易与电网交互波动惩罚的共享储能电站优化配置与调度模型
算法·能源
935962 小时前
机考27 翻译21 单词14
c语言·数据结构·算法
回敲代码的猴子4 小时前
2月14日打卡
算法
blackicexs4 小时前
第四周第七天
算法
期末考复习中,蓝桥杯都没时间学了5 小时前
力扣刷题19
算法·leetcode·职场和发展
Renhao-Wan5 小时前
Java 算法实践(四):链表核心题型
java·数据结构·算法·链表
zmzb01035 小时前
C++课后习题训练记录Day104
开发语言·c++
honiiiiii6 小时前
SMU winter week4
c++