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;
}
相关推荐
南宫萧幕5 分钟前
自控PID+MATLAB仿真+混动P0/P1/P2/P3/P4构型
算法·机器学习·matlab·simulink·控制·pid
浪浪小洋1 小时前
c++ qt课设定制
开发语言·c++
charlie1145141911 小时前
嵌入式C++工程实践第16篇:第四次重构 —— LED模板,从通用GPIO到专用抽象
c语言·开发语言·c++·驱动开发·嵌入式硬件·重构
handler011 小时前
Linux: 基本指令知识点(2)
linux·服务器·c语言·c++·笔记·学习
故事和你911 小时前
洛谷-数据结构1-4-图的基本应用1
开发语言·数据结构·算法·深度优先·动态规划·图论
我叫黑大帅1 小时前
为什么map查找时间复杂度是O(1)?
后端·算法·面试
炽烈小老头2 小时前
【每天学习一点算法 2026/04/20】除自身以外数组的乘积
学习·算法
skilllite作者2 小时前
AI agent 的 Assistant Auto LLM Routing 规划的思考
网络·人工智能·算法·rust·openclaw·agentskills
香蕉鼠片3 小时前
MFC是什么
c++·mfc
心态与习惯4 小时前
Julia 初探,及与 C++,Java,Python 的比较
java·c++·python·julia·比较