ZOJ 2876 Phone list
ZOJ :: Problems :: Show Problem
問題
n個の文字列が与えられる。ある文字列が、もう一方の文字列のprefixになるような2つの文字列が存在するか判定する。
解法
O(n^2)の全探索だと間に合わない。sortして隣り合う文字列を調べるとo(nlogn)で判定できる。
コード
int main(){ int T,n; cin>>T; while(T--){ cin>>n; vector<string> nums(n); REP(i,n){ cin>>nums[i]; } bool ans = true; sort(nums.begin(),nums.end()); REP(i,n-1){ int j = i+1; if(nums[i].size() <= nums[j].size() && nums[i] == nums[j].substr(0,nums[i].size())){ ans = false; goto PRINT; } } PRINT: if(ans)cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
ZOJ 3123 Subsequence
問題
長さNの数列a[0],..,a[N]が与えられる。総和がSを超えるような連続する部分列の、最小の長さを求めよ。
解法
まず部分和sを計算する(s[i+1] = s[i] + a[i], s[0] = 0)。
するとa[i],...,a[j]の総和はs[j+1]-s[i]となるので、始点iを決めると、終点はS+s[i]の二分探索で求まる。
コード
int main(){ int T; cin>>T; while(T--){ int N,S; cin>>N>>S; vector<int> a(N); REP(i,N)cin>>a[i]; vector<int> sum(N+1); REP(i,N)sum[i+1] = sum[i]+a[i]; int ans = INF; REP(i,N){ int cond = S + sum[i]; vector<int>::iterator it = lower_bound(sum.begin(),sum.end(),cond); if(it != sum.end()){ ans = min(ans, (int)distance(sum.begin(),it) - i); } } if(ans == INF) ans = 0; cout<<ans<<endl; } return 0; }
AOJ 1174 Identically Colored Panels Connection
問題
問題文読んで。
解法
色の変化をdfsする。隣接するマスの判定もdfsで。
コード
int h,w,c; int dx[4] = {1,0,-1,0}; int dy[4] = {0,-1,0,1}; int p[8][8]; bool ck[8][8]; bool valid(int x, int y){ return x>=0&&x<w&&y>=0&&y<h; } void check(int x, int y, int c){ if(ck[y][x]||p[y][x]!=c) return; ck[y][x] = true; REP(r,4){ int nx = x+dx[r]; int ny = y+dy[r]; if(valid(nx,ny)){ check(nx,ny,c); } } } int dfs(int t){ int ret = 0; if(t==5){ memset(ck,0,sizeof(ck)); check(0,0,c); REP(y,h)REP(x,w)if(ck[y][x])ret++; }else{ int tmp[8][8]; memcpy(tmp,p,sizeof(p)); REP(nc,6){ memset(ck,0,sizeof(ck)); check(0,0,p[0][0]); REP(y,h)REP(x,w)if(ck[y][x])p[y][x] = nc; ret = max(ret,dfs(t+1)); memcpy(p,tmp,sizeof(tmp)); } } return ret; } int main(){ while(cin>>h>>w>>c,h){ c--; REP(y,h)REP(x,w)cin>>p[y][x],p[y][x]--; cout<<dfs(0)<<endl; } return 0; }
AOJ 1173 The Balance of the World
問題
括弧のバランスがとれているか判定。
解法
左括弧ならstackに入れ、右括弧ならstackから取り出す。
左括弧と右括弧の対応が違っていたり、左括弧が余っていたり、右括弧が多すぎたりすればNG
コード
bool solve(string str){ map<char, int> t; t['['] = 1; t[']'] = 1; t['('] = 2; t[')'] = 2; stack<char> stk; REP(i,str.size()){ if(str[i]=='['||str[i]=='('){ stk.push(t[str[i]]); }else if(str[i]==']'||str[i]==')'){ if(stk.empty()||stk.top()!=t[str[i]]) return false; else stk.pop(); } } return stk.empty(); } int main(){ string str; while(getline(cin,str)){ if(str==".") break; if(solve(str)) cout<<"yes"<<endl; else cout<<"no"<<endl; } return 0; }
AOJ 1172 Chebyshev's Theorem
問題
整数nに対し、n
解法
試し割りで素数判定
コード
bool isPrime(int n){ for(int i = 2; i*i<=n; i++){ if(n%i == 0) return false; } return true; } int main(){ int n; while(cin>>n,n){ int ans = 0; FOR(i,n+1,2*n+1){ if(isPrime(i))ans++; } cout<<ans<<endl; } return 0; }
Project euler Problem 57
式をぼーっと眺めてると
A_(n+1) = A_n + 2*B_n, B_(n+1) = A_n + B_nだと気づいたのでそのとおりに書いた。
a = 3 b = 2 count = 0 1000.times{ count += 1 if a.to_s.size > b.to_s.size a, b = a + 2*b, a + b } puts count