【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; } }
【AOJ 2619】Thread Tree
問題
Thread Tree | Aizu Online Judge
方針
- 木を作って順に辿って出力する.
- 英語つらいなって思ったけどそんなに難しくなかった.(これは方針ではない)
コード
#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 pb push_back using namespace std; struct TREE { int _d; string _name; vector<TREE*> _v; TREE(string name, int d){ _name = name; _d = d; } void add(TREE* t){ _v.pb(t); } void print(){ rep(i,_d) cout << "."; cout << _name << endl; rep(i, _v.size()){ _v[i]->print(); } } }; signed main(){ int n; int k1, k; string m1, m; TREE* v[1001]; TREE *t, *root; cin >> n; cin >> k1; cin >> m1; root = t = new TREE(m1, k1); v[1] = t; REP(i, 2, n+1){ cin >> k >> m; t = new TREE(m, v[k]->_d+1); v[k]->add(t); v[i] = t; } root->print(); }
木を作るのに苦労するなど. まだまだですね.
AtCoder Beginner Contest #60
問題はこちら. abc060.contest.atcoder.jp
問題A:Shiritori
文字列A, B, Cが3つ与えられた時, それらがしりとりになっているか判定せよ.
#include <iostream> using namespace std; signed main(){ string a, b, c; cin >> a >> b >> c; if(a[a.size()-1] == b[0] && b[b.size()-1] == c[0]) cout << "YES" << endl; else cout << "NO" << endl; }
問題B:Choose Integers
正の整数A, B, Cが与えられる. 正の整数を幾つか選び, をれをBで割った時, 余りがCとなるように整数を選ぶ事ができるか出力せよ. ただし, 正の整数はAの倍数でなければならない.
#include<iostream> using namespace std; signed main(){ int a, b, c; cin >> a >> b >> c; int tmp = a; int mod = 0; bool flag[101]; fill(flag, flag+100, false); mod = tmp % b; do{ flag[mod] = true; if(mod == c){ cout << "YES" << endl; exit(0); } tmp += a; mod = tmp % b; }while(!flag[mod]); cout << "NO" << endl; }
問題C:Sentou
スイッチを押すと, T秒お湯が出る. スイッチを押すタイミングが与えられるので, 合計何秒間お湯が出たかを出力せよ. お湯が出ている状態でスイッチを押すと, T秒延長されるのではなく押した瞬間からT秒間お湯が出力されるという点に注意.
#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 n, t; int data[200001]; signed main(){ cin >> n >> t; fill(data, data+200000, 0); rep(i, n){ cin >> data[i]; } int end = 0; int start = 0; int ans = 0; rep(i, n){ if(data[i] < end){ end = data[i] + t; }else{ ans += (end - start); start = data[i]; end = data[i]+t; } } ans += (end - start); cout << ans << endl; }
問題D:Simple Knapsack
ナップサック問題. ただし,
という制約がついている. このwの制約を利用することで全探索をすることができる. 各重さごとにvectorにpushしておき, それらをどれだけ使うかを4重ループにして試す.
#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 ALL(v) v.begin(), v.end() #define pb push_back using namespace std; typedef long long ll; ll N, W; signed main(){ ll w1, v1, _w, _v; cin >> N >> W; cin >> w1 >> v1; vector<ll> v[4]; v[0].pb(v1); REP(i, 1, N){ cin >> _w >> _v; v[(_w - w1)].pb(_v); } rep(i, 4){ sort(ALL(v[i])); reverse(ALL(v[i])); } ll ans = 0; rep(i, v[0].size()+1){ rep(j, v[1].size()+1){ rep(k, v[2].size()+1){ rep(l, v[3].size()+1){ _w = 0; _v = 0; rep(ii, i){ _w += w1; _v += v[0][ii]; } rep(ii, j){ _w += (w1+1); _v += v[1][ii]; } rep(ii, k){ _w += (w1+2); _v += v[2][ii]; } rep(ii, l){ _w += (w1+3); _v += v[3][ii]; } if(_w <= W){ ans = max(ans, _v); } } } } } cout << ans << endl; }
rateが868(highest)になった. かなり低いけど地道に頑張っていこう.
【AOJ 2565】Broken Audio Signal
問題
Broken Audio Signal | Aizu Online Judge
方針
- 区間を狭めていって, その区間によって結果を出力する.
- xが偶数番目のときに上界, 奇数番目のときに下界を決めることができる.
- xが連続した時はnone, 上界がないなど様々な場合分けがあってとてもつらい.
コード
#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 MAX_V 1000000000 using namespace std; typedef long long ll; int n; string data[10000]; ll toNum(string s){ return (int)atoi(s.c_str()); } string solve(){ ll upper, lower; string prev; upper = MAX_V * 2; lower = -MAX_V * 2; prev = to_string(upper); rep(i, n){ if(data[i] == "x"){ if(prev == "x") return "none"; // xが連続 if((i+1) % 2 == 1){ // odd upper = min(upper, toNum(prev)); if(i < n-1) upper = min(upper, toNum(data[i+1])); }else{ // even lower = max(lower, toNum(prev)); if(i < n-1) lower = max(lower, toNum(data[i+1])); } }else{ // 数字のときに正しいか判別 if((i+1)%2 == 1 && prev != "x"){ if((toNum(prev)) <= toNum(data[i])) return "none"; }else if(prev != "x"){ if((toNum(prev)) >= toNum(data[i])) return "none"; } } prev = data[i]; if(upper - lower < 2) return "none"; } if(upper - lower > 2) return "ambiguous"; return to_string((upper + lower) / 2); } signed main(){ while(cin >> n, n){ rep(i, n){ cin >> data[i]; } cout << solve() << endl; } }