6.6 训练参考

Parentheses_Balance

点击查看代码
#include<iostream>
#include<stack>
using namespace std;

int main() {
  int T;
  scanf("%d%*c", &T);
  while(T--) {
  	string str;
  	getline(cin, str);
  	bool flag = true;
	stack<char> s;
  	for(int i = 0; i < str.length(); i++) {
  	  if(str[i] == '(') s.push('(');
	  else if(str[i] == '[') s.push('[');
	  else if(str[i] == ')') {
	  	if(!s.empty() && s.top() == '(') s.pop();	
		else{ flag = false; break; }
	  }
	  else if(str[i] == ']') {
	  	if(!s.empty() && s.top() == '[') s.pop();	
		else{ flag = false; break; }
	  }
	}
	if(flag) flag = s.empty();
	if(flag) printf("Yes\n");
	else printf("No\n");
  }
  return 0;
} 
一道较为简单的考察数据结构的题目,了解题目含义后就可以使用双端队列或者栈来模拟就可以了,当然推荐肯定是栈 这题也提示套娃的结构之一栈

S-Tree

点击查看代码
#include<iostream>
using namespace std;

const int base = 9;
char tree[1<<base];

int main() {
  int n, m, kase = 0;
  while(scanf("%d", &n)==1 && n) {
    int x[base];
  	for(int i = 0; i < n; i++) {
  	  int temp;
	  scanf(" x%d ", &temp);
	  x[i] = temp-1; 	
	}
	scanf("%s", tree);
	char ans[1<<base] = {0};
	scanf("%d", &m);
	char buf[base];
	for(int i = 0; i < m; i++) {
	  scanf("%s", buf);
	  int pos = 0;
	  for(int j = 0; j < n; j++) {
	  	pos = pos*2+(buf[x[j]]-'0');
	  	
	  }
	  ans[i] = tree[pos];
	} 
	printf("S-Tree #%d:\n", ++kase);
	printf("%s\n\n", ans);
  }
  return 0;
} 

考察的就是满二叉树的静态数组结构,较为简单

Tree-Recovery

点击查看代码
#include<iostream>
#include<cstring>
using namespace std;

const int maxn = 30;
char n1[maxn], n2[maxn];

void print_tree(int s1, int e1, int s2, int e2) {
  if(s1 > e1 || s2 > e2) return;
  if(s1 == e1) {
  	printf("%c", n1[s1]);
  	return;
  }
  int pos;
  for(int i = s2; i <= e2; i++) if(n2[i] == n1[s1]) {
  	pos = i;
  	break;
  }
  print_tree(s1+1, s1+pos-s2, s2, pos-1);
  print_tree(s1+pos-s2+1, e1, pos+1, e2);
  printf("%c", n1[s1]);
}

int main() {
  while(scanf("%s%s", n1, n2) == 2) {
	print_tree(0, strlen(n1)-1, 0, strlen(n2)-1);
	printf("\n");
  }  
  return 0;
}

考察的是之前的变种,依然是抓住根是有根树的灵魂,抓住根就抓住了树就可以了,仍然是基础题

Patrol Robot

点击查看代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;

int map[10][10], dis[8][2] = {-2, 1, -2, -1, 2, 1, 2, -1, 1, 2, 1, -2, -1, 2, -1, -2};

struct Node{
  int x, y, cnt;
  Node(int x = 0, int y = 0, int cnt = 0) : x(x), y(y), cnt(cnt){}
};

int main() {
  char n1[5], n2[5];
  while(scanf("%s%s", n1, n2) == 2) {
  	memset(map, 0, sizeof(map));
	int ans, s1 = n1[0]-'a', e1 = n1[1]-'1', s2 = n2[0]-'a', e2 = n2[1]-'1';
  	queue<Node> q;
  	q.push(Node(s1, e1, 0));
    while(!q.empty()) {
	  Node n = q.front();
      q.pop();
      if(n.x == s2 && n.y == e2) {
      	ans = n.cnt;
      	break;
	  }
	  for(int i = 0; i < 8; i++) {
	  	if(n.x+dis[i][0] < 0 || n.x+dis[i][0] > 7 || n.y+dis[i][1] < 0 || n.y+dis[i][1] > 7 || map[n.x+dis[i][0]][n.y+dis[i][1]]) continue;
	  	map[n.x+dis[i][0]][n.y+dis[i][1]] = n.cnt+1;
	  	q.push(Node(n.x+dis[i][0], n.y+dis[i][1], n.cnt+1));
	  }
	}
	printf("To get from %s to %s takes %d knight moves.\n", n1, n2, ans);
  }
  return 0;
}

本题就是BFS的模板题,找好边界条件就可以了

Patrol Robot

点击查看代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;

const int maxn = 22;
int map[maxn][maxn], dmap[maxn][maxn][maxn], dis[4][2] = {1,0,-1,0,0,1,0,-1};

struct Node{
  int x, y, cnt, out;
  Node(int x = 0, int y = 0, int cnt = 0, int out = 0) : x(x), y(y), cnt(cnt), out(out) {}
};

int main() {
  int n, m, cnt, T, ans;
  scanf("%d", &T);
  while(T--) {
  	memset(map, 0, sizeof(map));
  	memset(dmap, 0, sizeof(dmap));
    scanf("%d%d%d", &n, &m, &cnt);
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        scanf("%d", &map[i][j]);
    ans = -1;
    queue<Node> q;
    q.push(Node(0, 0, 0, 0));
    while(!q.empty()) {
      Node t = q.front();
      q.pop();
      if(t.x==n-1 && t.y==m-1) {
      	ans = t.cnt;
      	break;
	  }
	  for(int k = 0; k < 4; k++) {
	    int i = dis[k][0], j = dis[k][1];
	    if(t.x+i < 0 || t.x+i >= n || t.y+j < 0 || t.y+j >= m) continue;
	    if(map[t.x+i][t.y+j]) {
	      if(t.out+1 > cnt || dmap[t.x+i][t.y+j][t.out+1]) continue;
	      dmap[t.x+i][t.y+j][t.out+1] = t.cnt+1;
	      q.push(Node(t.x+i, t.y+j, t.cnt+1, t.out+1)); 
		}else{
		  if(dmap[t.x+i][t.y+j][0]) continue;
		  dmap[t.x+i][t.y+j][0] = t.cnt+1;
	      q.push(Node(t.x+i, t.y+j, t.cnt+1, 0));
		}
	  }
	}
    printf("%d\n", ans);
  } 
  return 0;
}

本题是BFS的进阶版本,因为增加了障碍物的描述,因此我们可以简单的再原先图的存储下再增加一维来实现对于障碍物的存储,然后进行普通的BFS就可以了

Equilibrium Mobile题解:

点击查看笔者代码
#include<iostream>
#include<string>
#include<map>
using namespace std;

typedef unsigned long long ull;

int main() {
  int t;
  cin >> t;
  while(t--) {
  	string line;
  	cin >> line;
  	int base = 1, len = line.length();
  	map<ull, int> m;
  	for(int i = 0; i < len; i++) {
  	  if(line[i] == '[') base = base << 1; 
	  else if(line[i] == ']') base = base >> 1;	
	  else if(line[i] == ',') continue;
	  else {
	  	ull temp;
	  	sscanf(line.substr(i).c_str(), "%lld", &temp);
	  	temp = temp*base; 
	  	if(!m.count(temp)) m[temp] = 1;
	  	else m[temp] += 1;
	  	temp = temp/base;
	  	int cnt = 0;
	  	do {
	  	  cnt++;
		  temp /= 10;	
		} while(temp);
		i += cnt-1;
	  }
	}
	int maxn = 0, ans = 0;
	for(auto it = m.begin(); it != m.end(); it++) {
	  ans += it->second;
	  if(it->second>maxn) maxn = it->second;
	}
	cout << ans - maxn << endl;
  }
  return 0;
}

本题本质上考察的并不是树,注意对于一个天平平衡条件来说就是(笔者这边采用了并查集的思想)所有叶子结点*2^(深度-1)要想等,这边读者可以尝试构建几个正确的天平去验证,因此最后就非常简单了,统计叶子节点的祖先最多的,然后其他的进行修改就可以了,注意本题因为数据量过大,建议使用scanf不推荐使用cin(没有删掉缓冲区加速的话)

Petri_Net_Simulation
本题是简单的simualation题目,就是模拟,这种关系是在树的结构上建立,但是要注意对于显式安装和隐式安装的区分,否则会WA

点击查看笔者代码
/*
血的教训,uva上一定要初始化,否则会出现RE,呜呜 
*/

#include<iostream>
#include<cstring>
using namespace std;

constexpr int MAXN = 100 + 10;
int n, m, sum, kase = 0, cnt[MAXN], G[MAXN][MAXN][2];

bool getD() {
  memset(cnt, 0, sizeof(cnt));
  memset(G, 0, sizeof(G));
  cin >> n;
  if(!n) return false;
  for(int i = 1; i <= n; i++) cin >> cnt[i];
  cin >> m;
  for(int i = 0; i < m; i++) {
  	int temp;
  	while(scanf("%d", &temp)==1 && temp) {
  	  if(temp < 0) G[i][-temp][0]++;
	  else G[i][temp][1]++;
	}
  }
  cin >> sum;
  return true;
}

bool check(int pos) {
  for(int i = 1; i <= n; i++) 
  	if(cnt[i] < G[pos][i][0]) return false; 
  return true;
}

bool deal() {
  bool ok = true;
  for(int i = 0; i < m; i++) {
  	if(check(i)) {
  	  for(int j = 1; j <= n; j++) cnt[j] = cnt[j] + G[i][j][1] - G[i][j][0];
	  ok = false;
	  break;
	}
  }
  return ok;
}

void output(bool flag) {
  cout << "Case " << ++kase << ": ";
  if(flag) cout << "still live after " << sum << " transitions" << endl;
  else cout << "dead after " << sum << " transitions" << endl;
  cout << "Places with tokens:";
  for(int i = 1; i <= n; i++) {
  	if(cnt[i]) cout << " " << i << " (" << cnt[i] << ")";
  }
  cout << endl << endl;
}

int main() {
  while(getD()) { 
    bool flag = true;
  	for(int i = 0; i < sum; i++) {
  	  if(deal()) { flag = false; sum=i; break;}	
    } 
    output(flag);
  }
  return 0;
}

Spatial_Structures

就是四叉树的一种考察方式,当然此题有坑点,需要注意题目说的是<=64,要考虑64的情况,这边建议开大数组,否则会段错误

点击查看代码
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

constexpr int MAXN = 64 + 5;
int n, kase = 0, image[MAXN][MAXN];
int dx[4] = {0, 0, 1, 1};
int dy[4] = {0, 1, 0, 1};
vector<int> v;

bool getD() {
  cin >> n;
  if(!n) return false;
  v.clear();
  memset(image, 0, sizeof(image));
  if(n > 0) {
    char buf[MAXN];
	for(int i = 0; i < n; i++) {
      scanf("%s", buf); 
      for(int j = 0; j < n; j++) image[i][j] = buf[j]-'0';
	}
  }else{
  	int temp;
  	while(scanf("%d", &temp)==1 && temp!=-1) v.push_back(temp);
  }
  return true;
}

void getTree(int base, int x, int y, int len, int pre, int cur) { 
  int temp = image[x][y];
  bool flag = true;
  for(int i = x; i < x+len && flag; i++) 
  	for(int j = y; j < y+len && flag; j++) 
      if(temp != image[i][j]) flag = false;
  if(flag) {
  	if(temp) v.push_back(pre+cur*base);
  }else{
    for(int i = 0; i < 4; i++) getTree(base ? base*5 : 1, x+dx[i]*len/2, y+dy[i]*len/2, len/2, pre+cur*base, i+1);
  }
}

void toTree() { 
  getTree(0, 0, 0, n, 0, 1); 
  sort(v.begin(), v.end());
  cout << "Image " << ++kase << endl;
  int len = v.size();
  for(int i = 0; i < len; i++) {
  	cout << v[i];
  	if(i==len-1) cout << endl;
  	else if(i%12==11) cout << endl;
  	else cout << " ";
  }
  cout << "Total number of black nodes = " << len << endl;
}

void enCode() {
  int vlen = v.size(); n = -n;
  for(int i = 0; i < vlen; i++) {
  	int x = 0, y = 0, len = n, num = v[i];
  	while(num) {
  	  int dir = num % 5; num /= 5; 
	  len /= 2; x = x+dx[dir-1]*len; y = y+dy[dir-1]*len;	
	} 
	for(int k = x; k < x+len; k++)
	  for(int l = y; l < y+len; l++) image[k][l] = 1;
  }
  cout << "Image " << ++kase << endl;
  for(int i = 0; i < n; i++) { 
  	for(int j = 0; j < n; j++) 
  	  if(image[i][j]) cout << "*";
  	  else cout << ".";
  	cout << endl;
  }
}

int main() {
  while(getD()) {
  	if(kase) cout << endl;
	if(n > 0) toTree();
  	else enCode();
  }
  return 0;
} 

Accordian_Patience
对于数据结构的一种模拟,这边笔者采用暴力模拟,通过stack和vector来模拟,当然也可以采用其他方式来进行模拟

点击查看代码
#include<iostream>
#include<vector>
#include<stack>
#include<string>
using namespace std;

constexpr int MAXN = 52;
vector< stack<string> > v;

bool getD() {
  string buf;
  cin >> buf;
  if(buf == "#") return false;
  v.clear();
  stack<string> insert;
  insert.push(buf);
  v.push_back(insert);
  for(int i = 1; i < MAXN; i++) {
  	cin >> buf;
  	stack<string> temp; temp.push(buf);
  	v.push_back(temp);
  }
  return true;
}

bool check(int x, int y) {
  if(x < 0) return false;
  if(v[x].top()[0] == v[y].top()[0] || v[x].top()[1] == v[y].top()[1]) return true;
  return false;
}

void trans(int to, int from) {
  v[to].push(v[from].top());
  v[from].pop();
  if(v[from].empty()) v.erase(v.begin()+from);
}

void deal() {
  bool flag = true;
  while(flag) {
  	flag = false;
  	int len = v.size();
  	for(int i = 0; i < len; i++) {
  	  if(check(i-3, i)) { trans(i-3, i); flag = true; break; }
	  else if(check(i-1, i)) { trans(i-1, i); flag = true; break; }
	}
  }
}

void output() {
  int len = v.size();
  cout << len;
  if(len > 1) cout << " piles remaining: ";
  else cout << " pile remaining: ";
  for(int i = 0; i < len; i++) {
  	cout << v[i].size();
  	if(i < len-1) cout << " ";
  	else cout << endl;
  } 
}

int main() {
  while(getD()) {
  	deal();
  	output();
  }
  return 0;
}

10-20-30

这边就是按照题目所说的去实现,当然注意这边对于牌堆是一直处理,并不是符合10-20-30就拿走,而是拿到该牌堆不存在或者不满足10-20-30为止,对于draw的判断,就是类似于原先隐式图的讲解,因此对于状态的压缩查找不过本题数据量较小,可以暴力查找

点击查看代码
#include<iostream>
#include<queue>
#include<vector>
#include<string>
using namespace std;

queue<int> q;
vector< vector<int> > v;
vector<string> buf;
int pos = 0, cnt = 0, vlen = 7;

bool getD() {
  int temp;
  cin >> temp;
  if(!temp) return false;
  while(!q.empty()) q.pop();
  q.push(temp);
  pos = cnt = 0; vlen = 7;
  for(int i = 0; i < 51; i++) {
  	cin >> temp;
  	q.push(temp);
  }
  v.clear();
  buf.clear();
  vector<int> insert;
  for(int i = 0; i < 7; i++) v.push_back(insert); 
  return true;
}

void output(int pos) {
  if(pos == 1) cout << "Win : " << cnt+7 << endl;
  if(pos == 2) cout << "Loss: " << cnt+7 << endl;
  if(pos == 3) cout << "Draw: " << cnt+7+1 << endl;
}

bool check(int cur) { 
  int len = v[cur].size();
  if(len < 3) return false;
  if((v[cur][0]+v[cur][1]+v[cur][len-1])%10 == 0) { 
  	q.push(v[cur][0]); q.push(v[cur][1]); q.push(v[cur][len-1]);
  	v[cur].erase(v[cur].begin()+len-1); 
  	v[cur].erase(v[cur].begin(), v[cur].begin()+2);
  	if(v[cur].empty()) { v.erase(v.begin()+cur); vlen--; pos--; return false; }  
  	return true;
  }
  else if((v[cur][0]+v[cur][len-1]+v[cur][len-2])%10 == 0) { 
  	q.push(v[cur][0]); q.push(v[cur][len-2]); q.push(v[cur][len-1]); 
  	v[cur].erase(v[cur].begin()+len-2, v[cur].begin()+len); 
  	v[cur].erase(v[cur].begin());
  	if(v[cur].empty()) { v.erase(v.begin()+cur); vlen--; pos--; return false; } 
  	return true;
  }
  else if((v[cur][len-3]+v[cur][len-2]+v[cur][len-1])%10 == 0) { 
  	q.push(v[cur][len-3]); q.push(v[cur][len-2]); q.push(v[cur][len-1]);
  	v[cur].erase(v[cur].begin()+len-3, v[cur].begin()+len); 
  	if(v[cur].empty()) { v.erase(v.begin()+cur); vlen--; pos--; return false; }
  	return true;
  }
  return false;
}

string store() {
  string line;
  queue<int> temp = q;
  while(!temp.empty()) {
  	line = line + (char)('0'+temp.front());
  	temp.pop();
  }
  line = line + '0';
  for(int i = 0; i < vlen; i++) {
  	int nlen = v[i].size();
  	for(int j = 0; j < nlen; j++) line = line + (char)('0'+v[i][j]);
  	line = line + '0';
  }
  return line;
}

bool cmp(string& insert) {
  int len = buf.size();
  for(int i = 0; i < len; i++) if(buf[i] == insert) return true;
  return false;
}

void deal() {
  for(int i = 0; i < 7; i++) {
  	v[i].push_back(q.front());
  	q.pop();
  }
  buf.push_back(store());
  while(!q.empty()) { 
    if(v.empty()) {
      output(1); return;
	} 
    v[pos].push_back(q.front()); 
    q.pop(); 
	while(check(pos)) continue; 
	string insert = store();
	if(cmp(insert)) {
	  output(3); return;
	}
	cnt++;
	if(vlen) pos = (pos+1)%vlen;
    buf.push_back(insert);
  }
  output(2);
}

int main() {
  while(getD()) {
    deal();
  }
  return 0;
}

Tree_Reconstruction

本题笔者想不出比较好的解释方法,后面再来填坑吧-_-,下面是缝合版本(笔者前面写了,但是没有保存,呜呜

点击查看代码
#include<iostream>
#include<vector>
#define LOCA
using namespace std;

struct Node{
  int root, bs, bt, ds, dt;
  Node(int root = 0, int bs = 0, int bt = 0, int ds = 0, int dt = 0) : root(root), bs(bs), bt(bt), ds(ds), dt(dt) {}
};

constexpr int MAXN = 1000 + 10;
vector<int> v[MAXN];
int n, bfs[MAXN], dfs[MAXN];

bool getD() {
  if(scanf("%d", &n)!=1) return false;
  for(int i = 0; i < MAXN; i++) v[i].clear();
  for(int i = 0; i < n; i++) cin >> bfs[i];
  for(int i = 0; i < n; i++) cin >> dfs[i];
  return true;  
}



void setTree(int root, int bs, int bt, int ds, int dt) {
#ifdef LOCAL
  cout << root << endl;
  for(int i = bs; i < bt; i++) cout << bfs[i] << " "; cout << endl;
  for(int i = ds; i < dt; i++) cout << dfs[i] << " "; cout << endl;
#endif
  if(ds == dt-1) { v[root].push_back(dfs[ds]); return; }
  while(bs < bt && bfs[bs] != dfs[ds]) bs++;
  int des = bs, next = ds, ad = bs; 
  for( ; next < dt;) {
  	if(dfs[next] == bfs[ad]) { next++; ad++; } 
	else break; 
  }
  for(; des < bt; des++) if(bfs[des] == dfs[next]) break;
  int st = next, ed = ds;
  bool flag = true; 
  for(int i = ds, j = bs; i < dt; i++, j++) 
  	if(dfs[i]!=bfs[j]) { flag = false; break; }
  if(flag) {
  	for(int i = ds; i < dt; i++) v[root].push_back(dfs[i]); return;
  }
  for(int i = bs; i < des; i++) {
    int ok = true;
    for(int j = ds; j < dt; j++) if(dfs[j] == bfs[i]) { ok = false; break; }
    if(ok) continue;
  	v[root].push_back(bfs[i]);
  	if(i == des-1) ed = dt;
  	else{
  	  for(; ed < dt; ed++) if(dfs[ed] == bfs[i+1]) break;	
	}
 	setTree(bfs[i], des, bt, st, ed);
  	st = ed+1;
  }
}

void output() {
  for(int i = 1; i <= n; i++) {
  	cout << i << ":";
  	int len = v[i].size();
    for(int j = 0; j < len; j++) {
      cout << " " << v[i][j];
	}
	cout << endl;
  }
}

int main() {
  while(getD()) {
    setTree(bfs[0], 1, n, 1, n);
    output();
  }
  return 0;
} 

本题其实就是注意dfs和bfs的区别,注意bfs是判断各层根节点的关键,注意题目保证了bfs一定是递增节点,如果bfs[i]<bfs[i-1]的时候,就已经不是这一层了,接着就是从dfs[j]开始(j是上一个bfs[i-1]的位置开始)搜索看看有没有bfs[i]有的话,就是兄弟结点,没有就是儿子节点,然后跳出循环,代码实现如下

点击查看代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

constexpr int MAXN = 1000 + 10;
int n, bfs[MAXN], dfs[MAXN];
vector<int> out[MAXN];

bool getD() {
  if(scanf("%d", &n) != 1) return false;
  for(int i = 0; i < n; i++) cin  >> bfs[i];
  for(int i = 0; i < n; i++) cin >> dfs[i];
  for(int i = 0; i < MAXN; i++) out[i].clear();
  return true;
}

void getTree(int root, int bs, int bt, int ds, int dt) {//cout << root << " " << bs << " " << bt << " " << ds << " " << dt << endl; if(root == 0) exit(0);
  if(bs >= bt || ds >= dt) return;
  for( ; bs < bt; bs++) if(bfs[bs] == dfs[ds]) break;
  if(bs == bt) return;
  int pre = bfs[bs], pos = ds+1;
  vector<int> insert;
  insert.push_back(pre);
  for(int i = bs+1; i < bt; i++) {
  	if(bfs[i] < pre) break;
  	pre = bfs[i];
  	bool flag = true;
  	for(int j = pos; j < dt; j++) 
  	  if(dfs[j] == pre) {
  	    insert.push_back(pre);
		pos = j + 1;
		flag = false;
		break;	
	  }	
	if(flag) break;
  }
  //for(int i = 0; i < insert.size(); i++) cout << insert[i] << " "; cout << endl;
  int sta = ds+1, des = ds, len =  insert.size();
  if(len > 1) {
    for(; des < dt; des++) if(dfs[des] == insert[1]) break;
  }else{
  	des = dt;
  }
  int nbs = bs;
  if(len) {
  	int temp = insert[len-1];
  	for(; nbs < bt; nbs++) if(bfs[nbs] == temp) break;
  	nbs++;
  }
  for(int i = 0 ; i < len; i++) {
  	if(i != len-1) for( ; des < dt; des++) {
      if(dfs[des] == insert[i+1]) break;
	}
  	if (i==len-1) des = dt;
    out[root].push_back(insert[i]);	
    getTree(insert[i], nbs, bt, sta, des);
    sta = des+1;
  }
}

void output() {
  for(int i = 1; i <= n; i++) {
  	sort(out[i].begin(), out[i].end());
  	cout << i << ":";
  	int len = out[i].size();
    for(int j = 0; j < len; j++) {
      cout << " " << out[i][j];
	}
	cout << endl;
  }	
}

int main() {
  while(getD()) {
    getTree(bfs[0], 1, n, 1, n);	
    output();
  }
  return 0;
} 

A Dicey Problem

这边注意筛子是有方向性的,也就是通过上面的数字和面对人的数字来唯一确定,这个应该是一道简单的bfs问题,通过bfs以及对于各种状态的正确存储就可以了

点击查看代码**
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<vector>
using namespace std;
 
constexpr int ROW = 10+5, COL = 10+5;
int r, c, sta, des, up, front, G[ROW][COL];
bool vis[ROW][COL][70];
vector<int> ans;
string name;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int dicey[6][4] = {2,3,5,4 , 6,3,1,4, 6,5,1,2, 2,1,5,6, 3,6,4,1, 4,5,3,2};

struct Node{ 
  vector<int> move;	
  int x, y, up, front;
  Node(vector<int> move,  int x = 0, int y = 0, int up = 0, int front = 0) : move(move), x(x), y(y), up(up), front(front) {}
};

bool getD() {
  cin >> name;
  if(name == "END") return false;
  memset(G, 0, sizeof(G));
  memset(vis ,0, sizeof(vis));
  ans.clear();
  cin >> r >> c >> sta >> des >> up >> front;
  for(int i = 1; i <= r; i++) 
    for(int j = 1; j <= c; j++) cin >> G[i][j]; 
  return true;
}

void output() {
  cout << name << endl;
  if(ans.empty()) { cout << "  " << "No Solution Possible" << endl; return; }
  int len = ans.size();
  for(int i = 0; i < len; i++) {
  	if(i%9==0) cout << "  ";
  	if(i == len-1) { cout << "(" << ans[i]/100 << "," << ans[i]%100 << ")" << endl; }
  	else {
  	  cout << "(" << ans[i]/100 << "," << ans[i]%100 << ")" << ",";
	  if(i%9 == 8) cout << endl;	
	}
  }
}

void deal(int tx, int ty, int pup, int pfront, int& nup, int& nfront) {
  if(tx == 0) {
  	nfront = pfront;
  	int pos = 0;
	while(dicey[pup-1][pos] != pfront && pos<4) pos++;
	pos = (pos+4-ty)%4; 
	nup = dicey[pup-1][pos];
  }
  else{
  	if(tx == 1) { nfront = pup; nup = 7-pfront; }
  	else { nfront = 7-pup; nup = pfront; }
  }
}

int main() {
  while(getD()) {
    queue<Node> q;
    vector<int> v;
    v.push_back(sta*100+des);
    q.push(Node(v, sta, des, up, front));
    bool flag = false;
    while(!q.empty()) {
      Node temp = q.front(); q.pop(); 
      if(temp.x == sta && temp.y == des && flag) {
      	ans = temp.move; 
      	break;
	  }
      if(!flag) flag = true;
      for(int i = 0; i < 4; i++) {
        int nx = temp.x + dx[i], ny = temp.y + dy[i];
        if(nx > 0 && nx <= r && ny > 0 && ny <= c && (G[nx][ny] == temp.up || G[nx][ny] == -1)) {
          int nup, nfront; 
		  deal(dx[i], dy[i], temp.up, temp.front, nup, nfront); 
		  if(!vis[nx][ny][nfront*10+nup]) {
		  	vis[nx][ny][nfront*10+nup] = true;
		  	vector<int> insert = temp.move;
		  	insert.push_back(nx*100+ny);
		  	q.push(Node(insert, nx, ny, nup, nfront));
		  }
		}
	  }
	}
	output();
  }
  return 0;
} 

Spreadsheet_Calculator

这个是模拟EXCEL的一道题目,当然本题是通过dfs来判定是否循环,如果dfs搜索到还处于dfs状态的点,那么该点就是不可计算的,这边可以用-1表示未计算,0表示不可以计算,1表示正在计算

点击查看代码
#include<iostream>
#include<cstring>
#include<vector>
#include<string>
#include<cctype>
#include<sstream>
#include<iomanip>
using namespace std;

constexpr int MAXR = 20 + 5, MAXC = 10 + 5;
string sheet[MAXR][MAXC];
int r, c;
bool vis[MAXR][MAXC], nvis[MAXR][MAXC];
int out[MAXR][MAXC];

bool getD() {
  cin >> r >> c;
  if(r==0) return false;
  memset(vis, 0, sizeof(vis));
  memset(nvis, 0, sizeof(nvis));
  memset(out, 0, sizeof(out));
  for(int i = 0; i < 20; i++) 
  	for(int j = 0; j < 10; j++) sheet[i][j] = "0";
  for(int i = 0; i < r; i++)
    for(int j = 0; j < c; j++) cin >> sheet[i][j];
  return true;
}

int dfs(int x, int y) {
  if(nvis[x][y]) return 10000;
  if(vis[x][y]) return out[x][y];
  nvis[x][y] = true;
  vis[x][y] = true;
  string buf = sheet[x][y];
  if(buf[0]!='-') buf = '+'+buf; 
  vector<int> add, minus;
  bool ok = true;
  while(true) {
  	int pos = 1, len = buf.length();
  	for( ; pos < len; pos++) 
  	  if(buf[pos] == '+' || buf[pos] == '-') break;
    string insert = buf.substr(0, pos);
    if(isdigit(insert[1])) {
      stringstream ss(insert.substr(1));
      int temp;
      ss >> temp;
      if(insert[0] == '+') add.push_back(temp);
      else minus.push_back(temp);
	}else{
	  int temp = dfs(insert[1]-'A', insert[2]-'0');
      if(temp == 10000) ok = false;
      else{
        if(insert[0] == '+') add.push_back(temp);
        else minus.push_back(temp);
	  }
	}
	if(pos < len) buf = buf.substr(pos);    	
    else break;	  
  }
  if(!ok) {
  	out[x][y] = 10000;
  	return 10000;
  }
  int sum = 0, vlen = add.size();
  for(int i = 0; i < vlen; i++) sum += add[i];
  vlen = minus.size();
  for(int i = 0; i < vlen; i++) sum -= minus[i];
  nvis[x][y] = false;
  out[x][y] = sum;
  return sum;
}

bool check() {
  for(int i = 0; i < r; i++)
    for(int j = 0; j < c; j++)
      if(out[i][j] == 10000) return false;
  return true;
}

void output() {
  if(check()) {
  	cout << " ";
  	for(int i = 0; i < c; i++) cout << setw(6) << i;
  	cout << endl;
  	for(int i = 0; i < r; i++) {
  	  cout << (char)('A'+i);
  	  for(int j = 0; j < c; j++) cout << setw(6) << out[i][j];
	  cout << endl;	
	}
  }else{
  	for(int i = 0; i < r; i++)
  	  for(int j = 0; j < c; j++) 
  	    if(out[i][j] == 10000) cout << (char)('A'+i)	<< (char)('0'+j) << ": " << sheet[i][j] << endl; 
  }
  cout << endl;
}

int main() {
  while(getD()) {
  	for(int i = 0; i < r; i++)
  	  for(int j = 0; j < c; j++)
  	    if(!vis[i][j]) dfs(i, j);
  	output();
  }
  return 0;
} 

/*
注意本题的关键在于判断访问过以及正在访问(判断循环),因此可以通过两种状态来实现 
*/

Inspector's_Dilemma

这是一个欧拉图的变式,也就是说涉及到边的遍历,一般就需要通过orla,当然还需要注意orla需要是连通,那么连通块之间的连接需要耗费,同时连通块称为欧拉图也需要耗费

点击查看代码
/*
一说到边的遍历就要想到欧拉图,本题本质上是对欧拉路的一种拓展
注意无向图首先需要连通,其次才会考虑入度出度的问题,当然对于无向图就是考虑是奇度还是偶度
不同的连通块需要耗费n-1
连通块想要变成欧拉图其度数为奇数的个数最多只能为2,因为不要求打印路径因此就不需要进行dfs遍历 
*/

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;

constexpr int MAXN = 1000 + 10;
int v, e, t, kase = 0;
vector<int> road[MAXN];
vector<int> temp;
bool vis[MAXN], vis2[MAXN];

bool getD() {
  cin >> v >> e >> t;
  if(v==0 && e==0 && t==0) return false;
  for(int i = 1; i <= v; i++) road[i].clear();
  memset(vis, 0, sizeof(vis));
  memset(vis2, 0, sizeof(vis2));
  int x, y;
  for(int i = 0; i < e; i++) {
  	cin >> x >> y;
  	road[x].push_back(y); 
  	road[y].push_back(x);
  	vis2[x] = vis2[y] = true;
  }
  return true;
}

void getR(int pos) {
  temp.push_back(pos);
  int len = road[pos].size();
  for(int i = 0; i < len; i++) {
  	if(vis[road[pos][i]]) continue;
  	else {
  	  vis[road[pos][i]] = true;
  	  getR(road[pos][i]);	
	}
  }
}

int main() {
  while(getD()) {
  	int sum = 0, sum2 = -1;
	for(int i = 1; i <= v; i++) { 
  	  if(vis[i]) continue;
  	  if(!vis2[i]) continue;
  	  vis[i] = true;
  	  temp.clear();
  	  getR(i);
  	  int cnt = 0, len = temp.size();
  	  for(int j = 0; j < len; j++) if(road[temp[j]].size()%2) cnt++;
      if(cnt >= 2) cnt = (cnt-2)/2;
      sum += cnt;
      sum2++;
	} 
	if(e) cout << "Case " << ++kase << ": " << (sum+sum2+e)*t << endl;
	else cout << "Case " << ++kase << ": 0" << endl;
  }
  return 0;
}
posted @   banyanrong  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示