csp 23-05-1重复局面 && 2 矩阵运算

重复局面

问题:给出若干棋盘的表达,字符矩阵形式,判断每个棋盘局面出现的次数
我的思路:

字符串对比,但是感觉每一个棋盘和前面每一个比较太重复,太麻烦。想到可以只对比棋子的位置,每个棋子维护一个位置矩阵,然后在读入的时候,记录下所有棋子每次的坐标值,然后,从第二个棋盘开始,每个都和前面每个棋子对比,看是否一样。不一样就break,记为1,然后如果能走到最后一个棋子,则次数加一。
OMG,好神经啊,深思熟虑之后想的什么狗屎方法啊,麻烦死了,还不如一开始的重复方法。

优秀思路:

CCF-CSP真题《202305-1 重复局面》

#include <iostream>
#include <vector>
#include <map>
using namespace std;

int main(){
	int num;
	cin >> num;
	char chess[64];
	vector<int> ans(num);
	map<string, int> status_map;
	for(int i = 0; i < num; i++){
		for (int j = 0; j < 64; j++){
			cin >> chess[j];
		}
		if(status_map.count(chess)){
			status_map[chess] ++;	
		else
			status_map[chess] = 1;
		
		ans[i] = status_map[chess];		
	}
	for(int i = 0 ; i < num; i++)
		cout << ans[i] << endl;	
	return 0;
}

原来博主在读取一个棋盘计算完次数就输出了出现次数,感觉和题目要求不太一样,但其实提交之后是100分,但就是觉得不舒服,所以又用了一个vector存储结果,最后一并输出。

get:

一开始用数组,可能是初始化的什么的问题,提交就错误,换成vector就对了,那么以后遇到长度不一定的,尽量就用vector吧。
***直接用每个棋盘的表达式作为键,次数作为值,每次调用map[].count()可以获取该键值对的个数。
OMG,真的好牛,用了一个map,完美解决,也是第一次知道map还能这样用。我这知识也太贫瘠了,wuwuwuwu。

一些map的知识
#include <map>
using namespace std; 
map<KeyType, ValueType> myMap;
加入
myMap[key] = value;
删除
myMap.erase(key);

检查键是否存在
if (myMap.count(key) > 0) {
    // 键存在
}

auto it = myMap.find(key);
if (it != myMap.end()) {
    // 键存在
}
遍历
for (auto it = myMap.begin(); it != myMap.end(); ++it) {
    cout << it->first << " : " << it->second << endl;
}

矩阵运算

题目

一个向量×三个矩阵连乘,输出最后的结果

思路

最初的思路竟然是矩阵连乘,动态规划,真神经啊,三个矩阵,至于吗?但是确实有一点想到点上。

优秀思路

确实是要找一个最优的顺序,手动就可以了,毕竟就三个矩阵。根据矩阵运算的复杂度分析一下,这里看了其他博主的
CCF CSP题解:矩阵运算(202305-2)
上方博文截图
所以就是单纯的矩阵运算

#include <iostream>
#include <vector>
using namespace std;

int main(){
	int n,d;
	cin >> n >> d;
	vector<vector<long long> > Q(n,vector<long long>(d)), K(n,vector<long long>(d)), V(n,vector<long long>(d));
	vector<long long> W(n);
	for(int i = 0; i < n; i++){
		for(int j = 0; j < d; j++){
			cin >> Q[i][j];
		}
	}
	for(int i = 0; i < n; i++){
		for(int j = 0; j < d; j++){
			cin >> K[i][j];
		}
	}
	for(int i = 0; i < n; i++){
		for(int j = 0; j < d; j++){
			cin >> V[i][j];
		}
	}
	for(int i = 0; i < n; i++){
		cin >> W[i];
	}
	// K转置 * V 
	vector<vector<long long> > t(n,vector<long long>(d));
	for(int i = 0; i < d; i++){
		for(int j = 0; j < d; j++){
			for(int k = 0; k < n; k++ ){
				t[i][j] += K[k][i] * V[k][j];	
		}
	}
}
	// Q*
	vector<vector<long long> > ans(n,vector<long long>(d));
	for(int i = 0; i < n; i++){
		for(int j = 0; j < d; j++){
			for(int k = 0; k < d; k++ ){
				ans[i][j] += Q[i][k] * t[k][j];		
		}
	}
}
	// W*

  	long long out;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < d; j++){
			cout << ans[i][j] * W[i] << " ";
		}
		cout << endl;
	}
	return 0;
}
get

矩阵运算的话,一般都往顺序上想想,复杂度会降。
复杂度和矩阵的规模有关系,[i,k] X [k,j] 复杂度 = i * k *j
然后矩阵的运算是三层循环,i,j,k,前两层一个是左行,一个是右列,k是控制每行每列的的每一个
正常:ans[i][j] += Q[i][k] * t[k][j];
转置:ans[i][j] += Q[k][i] * t[k][j]; (行列互换)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值