#include
#include //队列容器
#include
#include
#include //定义了有关字符判断和处理的库函数
using namespace std;
const int maxn = 1000;
deque readyQ;
queue blockQ;
int n,quantum,c[5],var[26],ip[maxn];//n为程序数,quantum为每次最多运行时间,c[5]中存储5总语句需要执行的时间
//var[26]代表26个字母变量对应的值
bool locked; //标识是否锁
char prog[maxn][10];//存储第maxn个程序对应的语句
void run(int pid){
int q = quantum;
while(q > 0){
char *p = prog[ip[pid]]; //ip[pid]是程序pid的当前行号。所有的程序都存在prog数组 获得pid程序的第ip[pid]语句
switch(p[2]){//判断是哪条语句
case '=' :
var[p[0] - 'a'] = isdigit(p[5]) ? (p[4] - '0') * 10 + p[5] - '0' : p[4] - '0'; //变量对应的值不超过100,需要判断否有十位
q -= c[0] ; //最多执行时间-已赋值语句执行时间
break;
case 'i' : //print var
printf("%d: %d\n",pid+1, var[p[6] - 'a']); //p[6] 代表输出的变量; var[ p[6] - 'a']代表这个变量对应的值
q -= c[1];
break;
case 'c': //lock
if(locked){ //如果之前已锁则加入堵塞队列
blockQ.push(pid); return;//加入阻塞队列后,退出循环,则未解锁之前这个程序中的语句不再执行
}
locked = true;
q -= c[2] ;
break;
case 'l': //unlock
locked = false;
if(!blockQ.empty()){ //当unlock执行完毕后,阻止队列的第一个程序进入等待队列的首部
int pid2 = blockQ.front();
blockQ.pop();
readyQ.push_front(pid2);
}
q -= c[3] ;
break;
case 'd': //end
return;
}
ip[pid]++; //此时ip[pid]为程序pid中未执行语句的第一行
}
readyQ.push_back(pid); //一条语句结束后,判断此次时间片是否用完,如用完则该程序pid退出,否则继续执行程序pid的下一条语句
}
int main(){
int T; //cases数
scanf("%d",&T);
while(T--){
scanf("%d %d %d %d %d %d %d",&n,&c[0],&c[1],&c[2],&c[3],&c[4],&quantum);
memset(var,0,sizeof(var));
int line = 0;
for(int i = 0; i < n; i++){ //存储所有程序的语句到prog,ip[i]记录程序i的第一条语句所在位置
fgets(prog[line++],maxn,stdin); //从指定的流中每次读取一行,存储在prog[line]数组中,maxn指最大字符1024
ip[i] = line - 1; //程序i的第一条语句所在位置
while(prog[line - 1][2] != 'd')//prog为二维数组 存储语句 因为语句的第三为是确定的,故判断第三位,如果是d则表示是end 结束输入
fgets(prog[line++],maxn,stdin);
readyQ.push_back(i); //存储完语句,准备工作完成,将程序加入准备队列
}
locked = false;
while(!readyQ.empty()) {
int pid = readyQ.front(); //获得准备队列队首程序
readyQ.pop_front(); //出队
run(pid); //执行程序
}
if(T) printf("\n");
}
return 0;
}
#include
#include
using namespace std;
const int MAXN = 1010;
int n,target[MAXN];
int main() {
while(scanf("%d",&n) && n) { //定义输入格式 如果输入的非0 则继续
for(;;) { //不知道输入数据有多少个
stack s; //初始化栈s
int A = 1, B = 1;
//每组输入数据第一个为0时结束输入
scanf("%d",&target[1]);
if(target[1] == 0) {
printf("\n"); //注意输入为0时需要空行
break; //跳出for循环
}
for(int i = 2; i <= n; i++) { //从1开始
scanf("%d", &target[i]);
}
int ok = 1;
while(B <= n) {
if(A == target[B]) {
A++;
B++;
} else if(!s.empty() && s.top() == target[B]) {
s.pop();
B++;
} else if(A <=n) s.push(A++);
else {
ok = 0;
break;
}
}
printf("%s\n",ok ? "Yes" : "No");
}
}
return 0;
}
#include
#include
#include
#include
using namespace std;
//由Expression = Matrix | "(" Expression Expression ")"可以得到左括号和右括号是相匹配的,并且括号对数比矩阵数多一
//故可以遇到左括号忽略,遇到矩阵入栈,遇到右括号出栈。 如果格式定义为AB则错误
struct Matrix {
int a,b; //成员变量
Matrix(int a = 0, int b = 0) : a(a),b(b){} //构造函数 先将a和b初始化为0,若主函数里的调用函数中参数a和b不为零,则a=a,b=b;
} m[26]; //m[26] 结构体数组
stack s;
int main(){
int n;
cin >> n;
for(int i = 0; i < n; i++){
string name;
cin >> name;
int k = name[0] - 'A'; //string 类型(name)没有减号运算符,字符类型有!
cin >> m[k].a >> m[k].b;
}
string expr;
while(cin >> expr){
int len = expr.length();
bool error = false;
int ans = 0;
for(int i = 0; i < len; i++){
if(isalpha(expr[i])) s.push(m[expr[i] - 'A']);
else if(expr[i] == ')'){
Matrix m2 = s.top(); s.pop();
Matrix m1 = s.top(); s.pop();
if(m1.b != m2.a) { error = true; break;
}else{
ans += m1.a * m1.b * m2.b;
s.push(Matrix(m1.a,m2.b));
}
}
}
if(error) printf("error\n"); else printf("%d\n",ans);
}
return 0;
}
链表 有指针域和数据域
也可用两个数组替代指针:next数组表示结点的地址,data数组表示数据的地址 ||||| next[0]中存储的值是下一个结点的地址,同时也是本个结点的数据地址(另一个数组存储数据)
#include
#include
const int maxn = 100000 + 5;
int last, cur, next[maxn]; //光标位于cur字符之后
char s[maxn] ;
/*
采用链表
将输入的每个字符都存到字符串列表s[1~n]
用next[i]表示当前显示屏中s[i]右边的字符编号(即在s中的下标)
next[0~n-1] next[0]表示s[1]
cur表示光标位置 cur=1表示当前光标在s[1]的右边 cur=0表示当前光标在 虚拟字符s[0]右边
*/
s[next[i]] s[next[next[i]]] s[next[next[next[i]]]]
int main(){
while(scanf("%s",s+1) == 1) { //从s[1]开始存储字符
int n = strlen(s+1) ; //输入保存在s[1],s[2]...中
last = cur = 0;
next[0] = 0;
for(int i = 1; i <= n;i++){
char ch = s[i];
if(ch == '[') cur = 0;
else if(ch == ']') cur = last;
else{
next[i] = next[cur];
next[cur] = i; //next中存储光标位置
if(cur == last) last = i;//一般来说当前光标和最后光标相同,如果cur移动到首部,则最后光标位置不变
cur = i; //移动光标
}
}
for(int i = next[0]; i != 0; i = next[i])
printf("%c",s[i]);
printf("\n");
}
return 0;
}
分析:由题意知该二叉树为满二叉树(所有结点从上到下从左到右编号为1、2、3....2^D-1)。每个结点初始状态为关闭。有很多个小球,小球在某结点处如果结点状态为关闭,往左下走,同时改变结点状态,否则往右下走,同时改变结点状态。问有D层二叉树,第i个小球会落到哪个叶子结点。
思路:
初始化结点状态数组为0,
for循环让i个小球下落,每次下落需先改变当前结点状态在下落(如果先下落再改变之前的结点状态的话会比较麻烦),直到下落的结点出界。
最后一次循环下落的值即为所求的叶子编号。
#include
#include
const int maxd = 20;//D<=20
int s[1<n) break; //这样判断更具有一般性
}
}
printf("%d\n",k/2); //“出界”之前的叶子编号
}
}
return 0;
}
但是!!!这样的实现有个很大的缺点,运算量太大。提交后会出现超时提醒。
改进:每个小球都会落在根节点上,因此前两个小球必然是一个左子树,一个在右子树。一般地,只需看小球编号的奇偶性,就能知道它最终在哪颗子树中,对于拿些落入根结点左子树的小球来说,只需知道该小球是第几个落在根的左子树里的,就可以知道它下一步往左还是往右。以此类推,直到小球落到叶子上。
如果使用题目中给出的编号I,则当I是奇数时,它是往左走的第(I+1)/2个小球,如果I是偶数,它是往右走的第I/2个小球。这样可以直接模拟最后一个小球的路线。
I是奇数往左走是因为初始结点是关闭的,要改变结点状态然后往左子结点走。
I是偶数时结点状态是开的,要改变结点状态然后往右子结点走。
然后每个结点都可看作是根结点。
#include
#include
int main(){
int l;
while(scanf("%d",&l) && l!=-1){
for(int i = 0; i < l; i++){
int D,I;
scanf("%d %d",&D,&I);
int k = 1;
for(int i=1; i < D;i++){ //模拟最后一个小球路线 到D-1层即可
if(I%2){ k = k*2; I = (I+1)/2;} //I%2的可能值0、1
else {k = k*2+1;I/=2;}
}
printf("%d\n",k);
}
}
return 0;
}
6-7 二叉树的层次遍历 uva122 构造树,bfs,添加结点
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 256 + 10;
//定义结点结构
struct Node{
bool have_value;//是否有值 (因为由结点构造树是不按顺序的,有可能从根到某个叶结点的路径上有的结点没有在输入中给出,或者给出超过了一次)
int v; //保存结点的值
Node* left,*right;//左右子结点
//结构体的构造函数
Node():have_value(false),left(NULL),right(NULL){}
};
Node* root; //根结点
//申请新结点
Node* newnode(){
return new Node();
}
//添加新结点
bool failed;
void addnode(int v,char *s){
int n = strlen(s);
Node* u = root;//指向根结点的指针
for(int i = 0; i < n; i++){
if(s[i] == 'L'){
if(u -> left == NULL) u->left = newnode();
u = u->left;
}else if(s[i] == 'R'){
if(u -> right == NULL) u->right = newnode();
u = u->right;
}
}
if(u->have_value) failed = true; //如果此结点之前已有值则创建结点失败
u->v = v;
u->have_value = true;
}
//释放二叉树 清内存
void remove_tree(Node* u){
if(u == NULL) return;
remove_tree(u->left);
remove_tree(u->right);
delete u;
}
//读入
char s[maxn];
bool read_input(){
failed = false;
remove_tree(root); //创建树之前先清空
root = newnode(); //根结点
for(;;){
if(scanf("%s",s) != 1) return false;
if(!strcmp(s,"()")) break;
int v;
sscanf(&s[1],"%d",&v);
addnode(v,strchr(s,',') + 1);
}
return true;
}
//树的层次遍历 广度优先遍历
bool bfs(vector& ans){
queue q; //q队列存放结点
ans.clear();
q.push(root);
while(!q.empty()){
Node* u = q.front(); q.pop();
if(!u->have_value) return false;
ans.push_back(u->v); //记录本结点值
if(u->left != NULL) q.push(u->left);//左孩子结点入队
if(u->right != NULL) q.push(u->right); //右孩子结点入队
}
return true;
}
int main(){
vector ans;
while(read_input()){
if(!bfs(ans)) failed = 1;
if(failed) printf("not complete\n");
else{
for(int i = 0; i < ans.size();i++){
if(i != 0) printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
}
return 0;
}