计科数据《算法设计与分析》第3次上机作业

问题 A: 算法10-6~10-8:快速排序

#include
using namespace std;
#define int long long
#define fer(i,a,b) for(int i=a;i<b;i++)
const int N=1e5+5,mod=1e9+7;
int a[N];
int partition(int a[],int l,int r){
	int i=l,j=r;
	int x=a[l];
	while(i<j){
		while(i<j&&a[j]>=x)j--;
		a[i]=a[j];
		while(i<j&&a[i]<=x)i++;
		a[j]=a[i];
	}
	a[i]=x;
	return j;
}
void quicksort(int a[],int l,int r){
	int t;
	if(l<r){
		t=partition(a,l,r);
		quicksort(a,l,t-1);
		quicksort(a,t+1,r); 
	}
}
signed main(){

	int n;cin>>n;
	fer(i,0,n)cin>>a[i];
	quicksort(a,0,n-1);
	fer(i,0,n)cout<<a[i]<<" ";
	cout<<endl;
	
	return 0;
}

问题 B: 黑白棋子的移动

有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,右边有两个空位,如下图为n=5的情形:
○○○○○●●●●●__
移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子,且棋子均在最右端。如n=5时,成为:__○●○●○●○●○●
n=7时输出

step 0:ooooooo*******--
step 1:oooooo--******o*
step 2:oooooo******--o*
step 3:ooooo--*****o*o*
step 4:ooooo*****--o*o*
step 5:oooo--****o*o*o*
step 6:oooo****--o*o*o*
step 7:ooo--***o*o*o*o*
step 8:ooo*o**--*o*o*o*
step 9:o--*o**oo*o*o*o*
step10:o*o*o*--o*o*o*o*
step11:--o*o*o*o*o*o*o*

观察发现,n>4时可递归至4,n==4时为边界条件可退出
万能头文件导致move函数被占用,自己写函数不要用move
输出要控制宽度
blank标记空位第一格的下标,可不断跳变

#include
using namespace std;
#define int long long
#define fer(i,a,b) for(int i=a;i<b;i++)
const int N=1e5+5,mod=1e9+7;
char c[N];
int n,blank,cnt;
void print(){
	cout<<"step"<<fixed<<setw(2)<<cnt++<<":";
	fer(i,0,2*n+2)cout<<c[i];
	cout<<endl;
}
void mv(int k){
	fer(j,0,2){
		c[blank+j]=c[k+j];
		c[k+j]='-';
	}
	blank=k;
	print();
}
void solve(int n){
	if(n==3){
		mv(3);
		mv(7);
		mv(1);
		mv(6);
		mv(0);
	}else{
		mv(n);
		mv(2*n);
		solve(n-1);
	}
}
signed main(){
	cin>>n;
	blank=2*n;
	fer(i,0,n)c[i]='o';
	fer(i,n,2*n)c[i]='*';
	c[blank]='-';
	c[blank+1]='-';
	print();
	solve(n-1);
	return 0;
	
}

问题 C: 4.4.3 矩阵连乘

题目描述
假设你必须评估一种表达形如 ABCDE,其中 A,B,C,D,E是矩阵。
既然矩阵乘法是关联的,那么乘法的顺序是任意的。然而,链乘的元素数量必须由你选择的赋值顺序决定。
例如,A,B,C分别是 50×10 ,10×20 和 20×5的矩阵。
现在有两种方案计算 A * B * C ,即(A * B) * C 和 A*(B * C)。
第一个要进行15000次基本乘法,而第二个只进行3500次。
你的任务就是写出一个程序判定以给定的方式相乘需要多少次基本乘法计算。
输入包含两个部分:矩阵和表达式。
输入文件的第一行包含了一个整数 n,(1≤n≤26), 代表矩阵的个数。
接下来的n行每一行都包含了一个大写字母,说明矩阵的名称,以及两个整数,说明行与列的个数。
第二个部分是若干个矩阵表达式,每行的数据保证是一个矩阵,一个括号以及其内部可视为一个矩阵,括号内部包含两个矩阵.
输出
对于每一个表达式,如果乘法无法进行就输出 " error "。否则就输出一行包含计算所需的乘法次数。
输入

9
A 50 10
B 10 20
C 20 5
D 30 35
E 35 15
F 15 5
G 5 10
H 10 20
I 20 25
A
B
C
(AA)
(AB)
(AC)
(A(BC))
((AB)C)
(((((DE)F)G)H)I)
(D(E(F(G(HI)))))
((D(EF))((GH)I))

输出

0
0
0
error
10000
error
3500
15000
40500
47500
15125

用结构体存储矩阵,栈里存的是int下标
遇到’('则从栈中弹出两个矩阵相乘,得到新矩阵保存并入栈
弹出顺序别弄反,先弹出的是第二个乘数
每次cin>>string后刷新矩阵及下标

#include
using namespace std;
#define int long long
#define fer(i,a,b) for(int i=a;i<b;i++)
int n,blank,cnt;
struct node{
	int r,c;
};
int cal(int a,int b,int c,int d){
	if(b!=c)return -1;
	else return a*b*d;
}
int k;
signed main(){
	cin>>n;
	node m[2*n+1];
	fer(i,0,n){
		char c;cin>>c;
		int a,b;cin>>a>>b;
		m[c-'A'].r=a;
		m[c-'A'].c=b;
	}
	string s;
	while(cin>>s){
		k=n;
		int sum=0;
		bool f=1;
		if(s.size()==1){
			cout<<"0"<<endl;
			continue;
		}
		stack<int> matrix;
		fer(i,0,s.size()){
			if(s[i]=='(')continue;
			else if(s[i]>='A'&&s[i]<='Z'){
				matrix.push(s[i]-'A');
			}else if(s[i]==')'){
				int t1=matrix.top();matrix.pop();
				int t2=matrix.top();matrix.pop();
				int res=cal(m[t2].r,m[t2].c,m[t1].r,m[t1].c);
				if(res<0){
					f=0;break;
				}else{
					sum+=res;
					m[k].r=m[t2].r;m[k].c=m[t1].c;
					matrix.push(k);
					k++;
				}
			}
		}
		if(f)cout<<sum<<endl;
		else cout<<"error"<<endl;
	}
	return 0;
}

你可能感兴趣的:(buctoj,算法)