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;
}