19西电西工大

1.WPL(哈夫曼编码)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 40;
int a[40];		// 字符频率 
int main(){
	int n;
	while(scanf("%d", &n)==1) {
		for(int i=0; i<n; i++) scanf("%d", &a[i]);
		sort(a, a+n);		// 系统排序函数 a[0, n) 
		int sum = 0; 
		for(int i=0; i<n-1; i++) {	// 每次选择两个最小的值做n-1次合并 
			a[i+1] = a[i]+a[i+1];	// 选择最前面两个数字做合并, 合并后a[i]不在我们的考虑中 
			sum += a[i+1];			// 累加中间合并的非叶子节点权值 
//			sort(a+i+1, a+n);		// 重新排序使得a[i+1,n)有序 
			for(int j=i+1; j<n-1; j++) {	// 用插入排序一趟的思想,将a[i+1]摆放到合适的位置 
				if(a[j]>a[j+1]) {			// 如果当前值比后继大,即非升序,需要交换 
					swap(a[j], a[j+1]);
				} else {					// 否则已经排好了 
					break;
				}
			}
		}
		printf("%d\n", sum);
	}
	return 0;
}

2.括号匹配问题

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 10000+10;
char s[maxn];		// 括号字符串 
char stack[maxn];	// 用数组来模拟栈 
int top = -1;	// 栈顶指针,指向栈顶元素 
int main(){
	int n;
	scanf("%d", &n); 
	while(n--) {
		scanf("%s", s);
		int len = strlen(s);
		int ok = 1;		// 标记是否匹配,默认匹配 
		top = -1;		// 清空栈 
		for(int i=0; i<len; i++) {		// 扫描整个字符串 
//			printf("%c--%c", s[i], top>=0?stack[]);
			if(s[i]=='(' || s[i]=='[') {	// 左括号,即待匹配字符,进入栈中 
				stack[++top] = s[i];		// 入栈 
			} else if(s[i] == ')') {
				if(top<0 || stack[top] != '(') {	// 栈为空或者不匹配 
					ok = 0;
					break;
				} else {					// 可以匹配,出栈 
					top--;
				}
			} else if(s[i] == ']') {
				if(top<0 || stack[top] != '[') {	// 栈为空或者不匹配 
					ok = 0;
					break;
				} else {					// 可以匹配,出栈 
					top--;
				}
			} 
		}
//		printf("%d--%d\n", ok, top==-1);
		ok = ok && top==-1;		// 所有右括号匹配完成并且没有多余的左括号
		printf("%s\n", ok? "Yes" :"No"); 
	}

	return 0;
}

3.六数码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;

const int maxn = 65433;
int vis[maxn];		// 标记数组
int Q[maxn];		// 队列
int front = 0, rear = 0;	// 队头和队尾指针 

int a[7];	// 状态(图中的结点)的数组形式 

void decoder(int u) {
	for(int i=1; i<=6; i++) {	// 分别取出u的六位数字,保存在a中 
		a[7-i] = u%10;
		u /= 10;
	} 
}
int trans1(int u) {	// 变化一 
	decoder(u);		// 解码 
	return a[4]*100000+a[1]*10000+a[3]*1000+a[5]*100+a[2]*10+a[6];		// 变化加编码 
} 
int trans2(int u) {	// 变化一 
	decoder(u);		// 解码 
	return a[1]*100000+a[5]*10000+a[2]*1000+a[4]*100+a[6]*10+a[3];		// 变化加编码 
} 


bool bfs(int s, int e) {
// 用bfs遍历图,从s出发判断是否可以访问到e
	front = rear = 0;	// 初始化队列 
	Q[rear++] = s;	// s加入队列 
	vis[s/10] = 1;	// 标记s已经访问
	 
	while(front<rear) {
		int u = Q[front++];	// 	出队
//		printf("%d\n", u); 
		if(u==e) {			// 访问当了 
			return true;
		} 
		
		int v = trans1(u);	// 变换1	
		if(!vis[v/10]) {	// 判断是否访问,如果没有访问加入队列,并标记访问 
			vis[v/10] = 1;
			Q[rear++] = v;
		}
		v = trans2(u);	// 变换2	
		if(!vis[v/10]) {	// 判断是否访问,如果没有访问加入队列,并标记访问 
			vis[v/10] = 1;
			Q[rear++] = v;
		}
	} 
	return false;
}
 

int main(){
	while(scanf("%d%d%d%d%d%d", &a[1],&a[2],&a[3],&a[4],&a[5],&a[6])==6) {
		memset(vis, 0, sizeof(vis));	// 初始化vis数组,标记所有结点没有访问 
		printf("%s\n", bfs(a[1]*100000+a[2]*10000+a[3]*1000+a[4]*100+a[5]*10+a[6], 123456)? "Yes":"No");
	} 

	return 0;
}

4.字符串解密

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 50 + 10;	// 问题规模
char s[maxn];				// 字符串:用字符数组来表示 
 
int main(){
	while(scanf("%s", s)==1) {
		int len = strlen(s);	// 字符串长度
		char pre;				// 数字之前的字符 
		for(int i=0; i<len; i++) {	// 扫描字符串 
			if(!('0'<=s[i] && s[i]<='9')) {	// 普通字符,非数字 
				printf("%c", s[i]);			// 先输出一个字符 
				pre = s[i];	
			} else {						// 数字 
				int num = 0;	// 解析到的数字
				while('0'<=s[i] && s[i]<='9') {
					num = num*10 + s[i] - '0';
					i++;		// 解析下一个数字 
				} 
				for(int j=0; j<num-1; j++) {	// 因为在解析数字之前已经打印过一次pre,所有这里只需要输出num-1次 
					printf("%c", pre);
				}
				i--;	// 因为当前s[i]已经为普通字符,回来和外层的for循环里的i++做抵消 
			}
		}	
		printf("\n");	// 处理一组数据后换行 
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值