问题 D: 4.4.3 矩阵连乘
题目描述
假设你必须评估一种表达形如 ABCDE,其中 A,B,C,D,E是矩阵。
既然矩阵乘法是关联的,那么乘法的顺序是任意的。然而,链乘的元素数量必须由你选择的赋值顺序决定。
例如,A,B,C分别是
50
×
10
50 \times 10
50×10 ,
10
×
20
10 \times 20
10×20 和
20
×
5
20 \times 5
20×5 的矩阵。
现在有两种方案计算 A * B * C ,即(A * B) * C 和 A*(B * C)。
第一个要进行15000次基本乘法,而第二个只进行3500次。
你的任务就是写出一个程序判定以给定的方式相乘需要多少次基本乘法计算。
输入格式
输入包含两个部分:矩阵和表达式。
输入文件的第一行包含了一个整数
n
,
(
1
≤
n
≤
26
)
n ,(1 ≤ n ≤ 26)
n,(1≤n≤26), 代表矩阵的个数。
接下来的n行每一行都包含了一个大写字母,说明矩阵的名称,以及两个整数,说明行与列的个数。
第二个部分是若干个矩阵表达式,每行的数据保证是一个矩阵,一个括号以及其内部可视为一个矩阵,括号内部包含两个矩阵
输出格式
对于每一个表达式,如果乘法无法进行就输出 " error "。否则就输出一行包含计算所需的乘法次数。
ssn:这个题干描述很容易就想到要问需要做乘法次数最少的组合,动态规划问题。其实老师还是有意没有把题目出的特别难。但还是有很多细节需要注意,没有什么特别的思路,可以写的很快,但我真的调试了很久才过。
总体思路:
1.栈:遇到左括号过,遇到字母push,遇到右括号pop出两个计算,并把结果push(也可以左括号也push,计算的时候多pop一下)。
2.完全是由于我自己知识的局限性,用的结构体,char型栈,操作真的很繁琐,代码量也有些大。观望大佬写的题解,用pair<int,int>会方便很多。
#include<bits/stdc++.h>
using namespace std;
struct Mri{
int hang;
int lie;
}M[5000];
int main()
{
int n;
string str;
cin>>n;
for(int i=0;i<n;i++){
char op;
cin>>op;
int j = op - 'A';
cin>>M[j].hang>>M[j].lie;
}
while(cin>>str){
if(str.length()<=1){
cout<<"0"<<endl;
continue;
}
stack<char> S;
int sum = 0;
int flag1 = 1,flag2 = 1;
Mri m;
int k = 1;
for(int i=0;i<str.length();i++){
if(str[i]=='(')
continue;
else if(isalpha(str[i]))
S.push(str[i]);
else if(str[i]==')'){
char ch1,ch2;
ch2 = S.top();
S.pop();
ch1 = S.top();
S.pop();
int j1,j2;
j1 = ch1-'A';
j2 = ch2-'A';
if(M[j1].lie!=M[j2].hang){
cout<<"error"<<endl;
flag1=0;
break;
}else{
sum += M[j1].hang*M[j1].lie*M[j2].lie;
}
char op = 'Z'+k;
M[op-'A'].hang = M[j1].hang;
M[op-'A'].lie = M[j2].lie;
S.push(op);
k++;
}
}
if(flag1) cout<<sum<<endl;
}
return 0;
}
问题 E: 4.4.4 打印队列
题目描述
有一些文件需要打印机打印,每个打印任务有1-9的优先级,优先级越高表示任务越急。打印机的运作方式为:首先从打印队列里取出一个任务J,如果队列里有比J更急的任务,则直接把任务放到打印 队列的尾部,否则打印任务J。输入打印队列中各个任务的优先级以你的任务在队列中的位置(队首位置为0)。输出该任务完成的时刻,所有任务都需要1分钟的打印时间。 例如,打印队列为{1,1,9,1,1,1},目前处于队首的任务最终完成时刻为5。以第三个样例为例,询问下标为0的打印时间,1 1 9 1 1 1中1有比他优先级高的,则把它放到队列末尾,变成1 9 1 1 1 1 同理变成 9 1 1 1 1 1,9取出直接打印 变为1 1 1 1 1,在依次打印即可,最后时间为5。
输入格式
输入:第一行为测试样例数T,每个样例第一行包括n(1<=n<=100)和m(0<=m<=n-1),其中n为打印任务数,m为你的任务序号(从0开始编号),第二行为n个数,为n个打印任务的优先级。
输出格式
对于每个测试用例,都单行输出你的作业任务打印完成的分钟数。
ssn:我真的,c++的模板的太神奇了,竟然连优先队列这种东西都有现成的。我写的时候我是真不知道啊啊啊啊。如果直接用priority_queue模板这题非常简单。
笔记:
priority_queue优先队列,取top为队列里的最大值。
#include<bits/stdc++.h>
using namespace std;
struct node{
int q;
bool intend;
};
int main()
{
int T;
cin>>T;
while(T--){
queue<node> Q;
//我受到了严重的暴击,怎么会有那么方便的东西我刚知道
priority_queue<int> P;
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++){
int x;
cin>>x;
Q.push({x,i==m});
P.push(x);
}
int cnt = 0;
while(!Q.empty()){
if(Q.front().q==P.top()){
cnt++;
if(Q.front().intend){
break;
}else{
Q.pop();
P.pop();
}
}else{
node k = Q.front();
Q.pop();
Q.push(k);
}
}
cout<<cnt<<endl;
}
return 0;
}