打卡第二十六天

1.暗恋

问题描述

同在一个高中,他却不敢去找她,虽然在别人看来,那是再简单不过的事。暗恋,是他唯一能做的事。他只能在每天课间操的时候,望望她的位置,看看她倾心的动作,就够了。操场上的彩砖啊,你们的位置,就是他们能够站立的地方,他俩的关系就像砖与砖之间一样固定,无法动摇。还记得当初铺砖的工人,将整个操场按正方形铺砖(整个操场可视为R行C列的矩阵,矩阵的每个元素为一块正方形砖块),正方形砖块有两种,一种为蓝色,另一种为红色。我们定义他和她之间的"爱情指标"为最大纯色正方形的面积,请你写一个程序求出"爱情指标"。

输入说明

第一行两个正整数R和C,R和C都不超过200。

接下来R行C列描述整个操场,红色砖块用1来表示,蓝色砖块用0来表示。

输出说明

一个数,表示他和她之间的"爱情指标"。

个人总结

用动态规划解决

dp[i][j]数组代表以(i,j)为右下角顶点的正方形的最大边长

首先边界dp全为1

再遍历除边界外所有节点,不断更新dp值

判断是否和周围三个格子颜色一致,若一致,dp值为其他三个格子dp的最小值+1

最后dp的最大值即最大边长

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int R, C;
    cin >> R >> C;

    vector<vector<int>> grid(R, vector<int>(C));
    
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            cin >> grid[i][j];
        }
    }

    // dp数组
    vector<vector<int>> dp(R, vector<int>(C, 1));

    int maxLen = 1;

    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {

            // 边界直接为1
            if (i == 0 || j == 0) {
                dp[i][j] = 1;
            } else {
                // 判断是否和周围三个格子颜色一致
                if (grid[i][j] == grid[i-1][j] &&
                    grid[i][j] == grid[i][j-1] &&
                    grid[i][j] == grid[i-1][j-1]) {

                    dp[i][j] = min({dp[i-1][j], dp[i][j-1], dp[i-1][j-1]}) + 1;
                } else {
                    dp[i][j] = 1;
                }
            }

            maxLen = max(maxLen, dp[i][j]);
        }
    }

    cout << maxLen * maxLen << endl;
    return 0;
}

2.木棍还原

问题描述

小明有一些相同长度的木棍,他将它们随机切割,直到所有切割后的短棍长度不超过50。现在他想把棍子恢复到原来的状态,但他忘了他原来有多少根棍子(但知道至少有两根),也不知道它们原来有多长。请帮助他,设计一个程序,计算出这些棍子的最小原始长度。

输入说明

输入包含多组数据,每组数据包含2行。

第一行包含切割后的短棍的数量n,n<=64。

第二行包含这些短棍的长度,由空格分隔。所有长度值都是大于0的整数。

最后一组数据之后是一个0,表示输入结束。

输出说明

为每组数据输出一行,包括一个整数,表示棍子原始的长度。

如果原始长度有多种可能,则输出最小的那个。

个人总结

目标 :拼出 m 根长度为 target_len 的长棍。

做法 :一个坑一个坑地填。填满第一根,再递归去填第二根,直到 m 根全部填满。

剪枝策略:

1.先大后小

2.若第一根放进去就失败,说明现在的target_len不行

3.若最后一根刚好凑齐target_len,但后面失败了,说明不行

4.跳过重复的长度

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int sticks[65];
bool used[65];
int n,total_len,target_len,m;


bool dfs(int cur_len, int start_idx, int completed){
	if(completed==m) return true;
	if(cur_len==target_len) return dfs(0,0,completed+1);//当前长棍拼满了,开始下一根
	for(int i=start_idx;i<n;i++){
		if(used[i]||cur_len+sticks[i]>target_len) continue;
		used[i]=true;
		if(dfs(cur_len+sticks[i],i+1,completed)) return true;//若加入这根,后面剩下的棍子还能否拼成功
		used[i]=false;//回溯
		//剪枝
		if(cur_len==0) return false;
		if(cur_len+sticks[i]==target_len) return false;
		while(i+1<n &&sticks[i]==sticks[i+1]) i++;//跳过长度相同的棍子
	}
	return false;
	
}

int main(){
	while(cin>>n&&n!=0){
		total_len=0;
		int max_stick=0;
		for(int i=0;i<n;i++){
			cin>>sticks[i];
			total_len += sticks[i];
			max_stick=max(max_stick,sticks[i]);
		}
		sort(sticks,sticks+n,greater<int>());//降序
		
		for(target_len=max_stick;target_len<=total_len;target_len++){
			if(total_len%target_len==0){
				m=total_len/target_len;
				memset(used, false, sizeof(used));
				if(dfs(0,0,0)){
					cout<<target_len<<endl;
					break;
				}
			}
		}
		
	}
	
	return 0;
}

3.拉丁正方形

问题描述

一种正方形的数字编排

1 2 3 4 5

2 1 4 5 3

3 4 5 1 2

4 5 2 3 1

5 3 1 2 4

是一个5*5的拉丁正方形,每个1到5的整数在每行每列都出现且出现一次。

写个程序计算N*N的的拉丁正方形的总数且要求第一行是: 1 2 3 4 5.......N

输入说明

一行包含一个整数N( 2<= N <= 7)

输出说明

只有一行,表示拉丁正方形的个数,且拉丁正方形的第一行为 1 2 3 . . . N.

个人总结

1.使用两个布尔数组 row[i][k]col[j][k] 来记录第 i 行或第 j 列是否已经使用了数字 k

2.按行填写

cpp 复制代码
#include <iostream>
using namespace std;

int n;
long long ans = 0;
bool row[10][10]; // row[i][num] 表示第i行是否用了数字num
bool col[10][10]; // col[j][num] 表示第j列是否用了数字num

// (r, c) 是当前正在填写的坐标
void dfs(int r, int c) {
    // 如果填完了最后一行,说明找到了一个合法方案
    if (r == n) {
        ans++;
        return;
    }

    // 确定下一个要填的坐标
    int next_r = r, next_c = c + 1;
    if (next_c == n) { // 如果这一行填完了,转到下一行开头
        next_r = r + 1;
        next_c = 0;
    }

    // 尝试在当前位置填入数字 i
    for (int i = 1; i <= n; i++) {
        if (!row[r][i] && !col[c][i]) { // 行和列都没用过这个数
            row[r][i] = col[c][i] = true; // 标记使用
            dfs(next_r, next_c);          // 递归填下一个
            row[r][i] = col[c][i] = false; // 回溯:恢复现场
        }
    }
}

int main() {
    cin >> n;

    // 初始化:第一行固定为 1, 2, 3, ..., n
    for (int j = 0; j < n; j++) {
        row[0][j+1] = true;
        col[j][j+1] = true;
    }

    // 从第二行(索引为1)的第一列(索引为0)开始搜
    dfs(1, 0);

    cout << ans << endl;
    return 0;
}

单词打卡

英语翻译

Generative AI refers to models that can generate new data similar to the training data. Popular generative models include Generative Adversarial Networks (GANs) and diffusion models. These models have been successfully applied in image synthesis, text generation, and audio creation. In a GAN framework, a generator and a discriminator compete with each other, improving the quality of generated data over time. Diffusion models, on the other hand, generate data by gradually removing noise from random inputs. Generative AI has shown great potential in fields such as content creation, drug discovery, and virtual reality. However, it also raises ethical concerns, including misinformation and data privacy issues, which require careful regulation.

生成式人工智能是指能够生成与训练数据相似的新数据的模型。主流的生成式模型包括生成对抗网络(GAN)和扩散模型。这类模型已成功应用于图像合成、文本生成和音频创作等领域。在生成对抗网络架构中,生成器与判别器相互博弈,使生成数据的质量随迭代不断提升。而扩散模型则通过逐步去除随机输入中的噪声来生成数据。生成式人工智能在内容创作、药物研发和虚拟现实等领域展现出巨大潜力。但它也引发了伦理层面的担忧,包括虚假信息和数据隐私问题,这些都需要加以审慎监管。

相关推荐
4ever.ov02 小时前
定时器/时间轮
开发语言·c++·c·muduo·llinux
C^h3 小时前
RTthread中的内存池理解
linux·数据库·c++·算法·嵌入式
lcj25113 小时前
蓝桥杯C++:数据结构(功能导向速查)
数据结构·c++·蓝桥杯
liulilittle3 小时前
eBPF tc prog
服务器·网络·c++·网络协议·tcp/ip·性能·perf
cui_ruicheng3 小时前
C++ 新特性(下):可变参数模板与 STL 扩展机制
开发语言·c++·c++11
|_⊙4 小时前
C++ 多态
c++
福楠4 小时前
现代C++ | 智能指针
c语言·开发语言·c++
汉克老师4 小时前
GESP5级C++考试语法知识(十二、递归算法(二))
c++·算法·记忆化搜索·时间复杂度·递归算法·gesp5级·gesp五级
旺仔.2914 小时前
顺序容器:Array 数组 详解
c++