【AOJ 1167】Pollock's conjecture
問題
Pollock's conjecture | Aizu Online Judge
方針
- 動的計画法を使う.
- nを表現するのに必要な正四面体の数の最小値 としたとき, はとして求めることができる.
- 1から順番にもとめておき, 入力したnを添え字にしてテーブルを出力する.
コード
#include<iostream> #include<vector> #define rep(i, n) REP(i, 0, n) #define REP(i, a, n) for(int i = a ; i < (int)n ; i++) #define INF 1e9 #define pb push_back using namespace std; typedef long long ll; #define MAX 1000001 signed main(){ int n; int ans_odd[MAX], ans[MAX]; vector<int> v1, v2; rep(i, 301){ int hoge = i * (i+1) * (i+2) / 6; v1.pb(hoge); if(hoge%2 == 1) v2.pb(hoge); } rep(i, 1000001){ ans[i] = ans_odd[i] = INF; } ans[0] = ans_odd[0] = 0; REP(i, 1, MAX){ REP(j, 1, v1.size()){ if(v1[j] > i) break; ans[i] = min(ans[i], ans[i - v1[j]]+1); } } REP(i, 1, MAX){ ans_odd[i] = i; REP(j, 1, v2.size()){ if(v2[j] > i) break; ans_odd[i] = min(ans_odd[i], ans_odd[i - v2[j]]+1); } } while(cin >> n, n){ cout << ans[n] << " " << ans_odd[n] << endl; } }
頭悪すぎて書くのにすごい時間がかかった…
【AOJ 1346】Miscalculation
問題
Miscalculation | Aizu Online Judge
方針
- ルール1は通常の優先順位(乗算→加算)で演算する.
- ルール2は左から順番に計算する.
- ルール1とルール2の結果が等しく, 入力した数字とも等しければU
- ルール1が入力した数字と等しければM, ルール2と等しければL, それ以外はIを出力する.
コード
#include<cctype> #include<iostream> using namespace std; typedef string::const_iterator State; int number(State &begin){ int ret = *begin - '0'; begin++; return ret; } int term(State &begin){ int ret = number(begin); while(true){ if(*begin == '*'){ begin++; ret *= number(begin); }else{ break; } } return ret; } int expression(State &begin){ int ret = term(begin); while(true){ if(*begin == '+'){ begin++; ret += term(begin); }else{ break; } } return ret; } int rule2(string s){ State begin = s.begin(); int ret = *begin - '0'; begin++; while(begin != s.end()){ if(*begin == '+'){ begin++; ret += *begin - '0'; }else{ begin++; ret *= *begin - '0'; } begin++; } return ret; } signed main(){ string s; int n; int ans1, ans2; cin >> s; cin >> n; State begin = s.begin(); ans1 = expression(begin); ans2 = rule2(s); if(ans1 == ans2 && ans1 == n){ cout << "U" << endl; }else if(ans1 == n){ cout << "M" << endl; }else if(ans2 == n){ cout << "L" << endl; }else{ cout << "I" << endl; } }
参考
構文解析の部分は以下の記事を参考にしました.
構文解析 Howto · GitHub
これでAOJ-ICPCの200が全部埋まりましたー, やったー!
【AOJ 2340】Carpenters' Language
問題
Carpenters' Language | Aizu Online Judge
方針
- 文法を見てみると, 実は挿入位置は関係なくてかっこの個数だけで判定できることが分かる.
- 左括弧, 右括弧それぞれの個数を保持しておき, 同じの時はYes, そうでないときはNoを出力する.
コード
#include<iostream> #define rep(i, n) REP(i, 0, n) #define REP(i, a, n) for(int i = a ; i < (int)n ; i++) using namespace std; typedef long long ll; signed main(){ int q; ll p, n; char c; ll open, close; open = close = 0; cin >> q; rep(i, q){ cin >> p >> c >> n; if(c == '('){ open += n; }else{ close += n; } if(open == close) cout << "Yes" << endl; else cout << "No" << endl; } }
【AOJ 1249】Make a Sequence
問題
Make a Sequence | Aizu Online Judge
方針
- 置くたびにm個以上つながっているかを調べる.
- 縦横斜めの3方向を探索するので, dx, dy, dzという配列を用意しておき3重ループする.
コード
#include<bits/stdc++.h> #define rep(i, n) REP(i, 0, n) #define REP(i, a, n) for(int i = a ; i < (int)n ; i++) #define m0(x) memset(x, 0, sizeof(x)) #define EMPTY -1 using namespace std; typedef pair<int, int> pii; int dx[3] = {-1, 0, 1}; int dy[3] = {-1, 0, 1}; int dz[3] = {-1, 0, 1}; int n, m, p; int peg[10][10][10]; pii coordinate[350]; int idx; bool check(int x, int y, int z){ rep(i, 3){ rep(j, 3){ rep(k, 3){ if(dx[i] == 0 && dy[j] == 0 && dz[k] == 0) continue; int len = 1; int sgn = 1; rep(l, 2){ int nx = x; int ny = y; int nz = z; while(true){ nx += (sgn * dx[i]); ny += (sgn * dy[j]); nz += (sgn * dz[k]); if(nx < 0 || n <= nx || ny < 0 || n <= ny || nz < 0 || n <= nz) break; if(peg[x][y][z] == peg[nx][ny][nz]) len++; else break; } if(len >= m) return true; sgn *= (-1); } if(len >= m) return true; } } } return false; } int getTurn(){ memset(peg, EMPTY, sizeof(peg)); rep(i, p){ int x = coordinate[i].first; int y = coordinate[i].second; bool ret = false; bool flag = false; rep(z, n){ if(peg[x][y][z] == EMPTY){ peg[x][y][z] = i % 2; idx = i; ret = check(x, y, z); // 何個連続しているか調べる flag = true; break; } } if(!flag) return 0; if(ret) return i+1; } return 0; } signed main(){ while(cin >> n >> m >> p, n || m || p){ rep(i, p){ cin >> coordinate[i].first >> coordinate[i].second; coordinate[i].first--; coordinate[i].second--; } int ret = getTurn(); if(ret == 0) cout << "Draw" << endl; else if(ret % 2 != 0) cout << "Black " << ret << endl; else cout << "White " << ret << endl; } }
【AOJ 2165】 Strange String Manipulation
問題
Strange String Manipulation | Aizu Online Judge
方針
- S,A,Cを総当りして, エントロピーが一番低くなる場合を探す.
- 誤差を考えて, epsを足さないと死んでしまう.
コード
#include<bits/stdc++.h> #define rep(i, n) REP(i, 0, n) #define REP(i, a, n) for(int i = a ; i < (int)n ; i++) #define eps 1e-9 #define INF 1e9 #define m0(x) memset(x, 0, sizeof(x)) using namespace std; signed main(){ int n; int I[300]; int r[300]; int o[300]; int freq[300]; while(cin >> n, n){ REP(i,1,n+1){ cin >> I[i]; } double minH = INF; int minS, minA, minC, idx; rep(s, 16){ rep(a, 16){ rep(c, 16){ r[0] = s; m0(freq); REP(i, 1, n+1){ r[i] = (a * r[i-1] + c) % 256; idx = (I[i] + r[i]) % 256; freq[idx]++; } double sum=0; rep(i, 256){ if(freq[i] == 0) continue; sum += ((-1) * (freq[i]/(double)n) * (log(freq[i]/(double)n))); } if(sum + eps < minH){ minH = sum; minA = a; minS = s; minC = c; } } } } cout << minS << " " << minA << " " << minC << endl; } }
参考
今週中に200を終わらせよう.
【AOJ 1368】Quality of Check Digits
問題
Quality of Check Digits | Aizu Online Judge
方針
- 4桁の数字(abcd)をループで作る.
- eを求め, それをチェック関数に投げる.
- abcdの各桁を0-9の数字で置き換え, 0になったら-1を返す.
- また, 連続する2桁を交換し(ただし, それぞれが違う文字のときのみ)0になったら-1を返す
- -1の数を数え, それが答えとなる.
コード
#include <iostream> #define rep(i, n) REP(i, 0, n) #define REP(i, a, n) for(int i = a ; i < (int)n ; i++) using namespace std; int table[10][10]; int check(int a, int b, int c, int d, int e){ rep(i, 10){ if(table[table[table[table[table[0][i]][b]][c]][d]][e] == 0 && i != a){ return -1; } } rep(i, 10){ if(table[table[table[table[table[0][a]][i]][c]][d]][e] == 0 && i != b){ return -1; } } rep(i, 10){ if(table[table[table[table[table[0][a]][b]][i]][d]][e] == 0 && i != c){ return -1; } } rep(i, 10){ if(table[table[table[table[table[0][a]][b]][c]][i]][e] == 0 && i != d){ return -1; } } rep(i, 10){ if(table[table[table[table[table[0][a]][b]][c]][d]][i] == 0 && i != e){ return -1; } } if(table[table[table[table[table[0][b]][a]][c]][d]][e] == 0 && a != b) return -1; if(table[table[table[table[table[0][a]][c]][b]][d]][e] == 0 && b != c) return -1; if(table[table[table[table[table[0][a]][b]][d]][c]][e] == 0 && c != d) return -1; if(table[table[table[table[table[0][a]][b]][c]][e]][d] == 0 && d != e) return -1; return 1; } signed main(){ // input rep(i, 10){ rep(j, 10){ cin >> table[i][j]; } } // check int ans = 0; rep(i, 10){ rep(j, 10){ rep(k, 10){ rep(l, 10){ int e = table[table[table[table[0][i]][j]][k]][l]; if(check(i, j, k, l, e) == -1) ans++; } } } } cout << ans << endl; }
【AOJ 1367】Rearranging a Sequence
問題
Rearranging a Sequence | Aizu Online Judge
方針
- 与えられたM個の値を逆順に出力する.
- 出力したかどうかを管理しておき, 1回も出力していない場合に限って出力を行う.
コード
#include<bits/stdc++.h> #define rep(i, n) REP(i, 0, n) #define REP(i, a, n) for(int i = a ; i < (int)n ; i++) using namespace std; int change[200001]; bool flag[200001]; signed main(){ int n, m; cin >> n >> m; rep(i, m){ cin >> change[i]; } fill(flag, flag+20000, false); reverse(change, change+m); rep(i, m){ if(!flag[change[i]]){ cout << change[i] << endl; flag[change[i]] = true; } } REP(i, 1, n+1){ if(!flag[i]) cout << i << endl; } }