2009-05-23
SRM234 Div1 Medium: WeirdRocks
Algorithm Tutorials: How To Find a Solution (by Dumitru) より。
Backtrackingで解く例(その3)。650点問題。
- とりあえず書いてみた
- 問題文の4つのTest Caseは全部通る
- 302.04points (42'45''), Failed System Test
- 最大ケース(8行10列)で落ちる...というか帰って来ないし
#define rep_(var,n) for(int var=-1;var<(n);var++) string join(vector<string> strs, const string &delim="") { int n=strs.size(); if (n==0) return ""; stringstream ss; ss << strs[0]; for(int i=1;i<n;i++) { ss << delim << strs[i]; } return ss.str(); } class WeirdRooks { public: string describe(vector<int> cols) { set<pair<int,int> > ans; int R=sz(cols); //1-8 int W=*max_element(all(cols)); int M=0; rep(i,R) M+=cols[i]; set<pair<int,vector<int> > > pat; int k=0; vector<int> m(W,-1); rep_(i0,cols[0]){ if(i0>=0){ k++; m[i0]=0; } if(R>=2) rep_(i1,cols[1]){ if(i1>=0){ if(m[i1]>=0) continue; k++; m[i1]=1; } if(R>=3) rep_(i2,cols[2]){ if(i2>=0){ if(m[i2]>=0) continue; k++; m[i2]=2; } if(R>=4) rep_(i3,cols[3]){ if(i3>=0){ if(m[i3]>=0) continue; k++; m[i3]=3; } if(R>=5) rep_(i4,cols[4]){ if(i4>=0){ if(m[i4]>=0) continue; k++; m[i4]=4; } if(R>=6) rep_(i5,cols[5]){ if(i5>=0){ if(m[i5]>=0) continue; k++; m[i5]=5; } if(R>=7) rep_(i6,cols[6]){ if(i6>=0){ if(m[i6]>=0) continue; k++; m[i6]=6; } if(R==8) rep_(i7,cols[7]){ if(i7>=0){ if(m[i7]>=0) continue; k++; m[i7]=7; } if(R==8) pat.insert(make_pair(k,m)); if(i7>=0){ k--; m[i7]=-1; } }//7 if(R==7) pat.insert(make_pair(k,m)); if(i6>=0){ k--; m[i6]=-1; } }//6 if (R==6) pat.insert(make_pair(k,m)); if(i5>=0){ k--; m[i5]=-1; } }//5 if (R==5) pat.insert(make_pair(k,m)); if(i4>=0){ k--; m[i4]=-1; } }//4 if (R==4) pat.insert(make_pair(k,m)); if(i3>=0){ k--; m[i3]=-1; } }//3 if (R==3) pat.insert(make_pair(k,m)); if(i2>=0){ k--; m[i2]=-1; } }//2 if (R==2) pat.insert(make_pair(k,m)); if(i1>=0){ k--; m[i1]=-1; } }//1 if (R==1) pat.insert(make_pair(k,m)); if(i0>=0){ k--; m[i0]=-1; } }//0 tr(pat,it){ int k=it->first; vector<int> m=it->second; vector<vector<bool> > sp(R,vector<bool>(W,false)); rep(r,R) rep(c,cols[r]) sp[r][c]=true; rep(c,W){ if(m[c]>=0) { // (c,m[i]) int r=m[c]; for(int j=0;j<=c;j++) sp[r][j]=false; for(int j=0;j<=r;j++) sp[j][c]=false; } } int sc=0; rep(r,R) rep(c,cols[r]) if(sp[r][c])sc++; ans.insert(make_pair(k,sc)); } vector<string> vs; tr(ans,it){ char buf[6]; sprintf(buf,"%d,%d",it->first,it->second); vs.pb(buf); } return join(vs," "); } };
- なんとかしたい。とりあえずパターンをlong longにしてみる
class WeirdRooks { public: string describe(vector<int> cols) { set<pair<int,int> > ans; int R=sz(cols); //1-8 int W=*max_element(all(cols)); int M=0; rep(i,R) M+=cols[i]; set<ll> pat; int k=0; ll m=0LL; vector<ll> m_(8,0LL); rep_(i0,cols[0]){ if(i0>=0){ m_[0] = m; m |= (1LL << (4*i0)); } if(R>=2) rep_(i1,cols[1]){ if(i1>=0){ if(m & (15LL <<(4*i1))) continue; m_[1] = m; m |= (2LL << (4*i1)); } if(R>=3) rep_(i2,cols[2]){ if(i2>=0){ if(m & (15LL <<(4*i2))) continue; m_[2] = m; m |= (3LL << (4*i2)); } if(R>=4) rep_(i3,cols[3]){ if(i3>=0){ if(m & (15LL <<(4*i3))) continue; m_[3] = m; m |= (4LL << (4*i3)); } if(R>=5) rep_(i4,cols[4]){ if(i4>=0){ if(m & (15LL <<(4*i4))) continue; m_[4] = m; m |= (5LL << (4*i4)); } if(R>=6) rep_(i5,cols[5]){ if(i5>=0){ if(m & (15LL <<(4*i5))) continue; m_[5] = m; m |= (6LL << (4*i5)); } if(R>=7) rep_(i6,cols[6]){ if(i6>=0){ if(m & (15LL <<(4*i6))) continue; m_[6] = m; m |= (7LL << (4*i6)); } if(R==8) rep_(i7,cols[7]){ if(i7>=0){ if(m & (15LL <<(4*i7))) continue; m_[7] = m; m |= (8LL << (4*i7)); } if(R==8) pat.insert(m); if(i7>=0) m=m_[7]; }//7 if(R==7) pat.insert(m); if(i6>=0) m=m_[6]; }//6 if (R==6) pat.insert(m); if(i5>=0) m=m_[5]; }//5 if (R==5) pat.insert(m); if(i4>=0) m=m_[4]; }//4 if (R==4) pat.insert(m); if(i3>=0) m=m_[3]; }//3 if (R==3) pat.insert(m); if(i2>=0) m=m_[2]; }//2 if (R==2) pat.insert(m); if(i1>=0) m=m_[1]; }//1 if (R==1) pat.insert(m); if(i0>=0) m=m_[0]; }//0 // cout << "pat.size = " << sz(pat) << endl; { vector<int> m(W,-1); vector<vector<bool> > sp(R,vector<bool>(W,false)); int k=0; tr(pat,it){ rep(i,W) m[i]=(((*it) >> (4*i)) & 15)-1; rep(r,R) rep(c,cols[r]) sp[r][c]=true; k=0; rep(c,W){ if(m[c]>=0) { // (c,m[i]) k++; int r=m[c]; for(int j=0;j<=c;j++) sp[r][j]=false; for(int j=0;j<=r;j++) sp[j][c]=false; } } int sc=0; rep(r,R) rep(c,cols[r]) if(sp[r][c])sc++; ans.insert(make_pair(k,sc)); } } vector<string> vs; tr(ans,it){ char buf[6]; sprintf(buf,"%d,%d",it->first,it->second); vs.pb(buf); } return join(vs," "); } };
最大ケースでも帰ってくるようになったが1分前後かかる。12975561パターンあるのでこんなのでは駄目かと。(とりあえずここまで)
SRM234 Div1 Easy: FractionSplit
- gcd()は自前
- 232.51points (7'54''), Passed system test
- intで足りるのかとか心配したけど大丈夫だったようだ
int gcd(int m, int n) { if (m == 0 || n == 0) return 0; if (m == 1 || n == 1) return 1; if (m == n) return m; while (1) { if (m == 0) return n; if (n == 0) return m; if (m > n) m %= n; else n %= m; } } class FractionSplit { public: vector<string> getSum(int n, int d) { vs ans; for(int x=2;n>0;x++){ // n/d >= 1/x : nx >= d int nr = n*x - d; if (nr >= 0){ // n/d - 1/x = (nx-d)/xd char buf[128]; sprintf(buf,"1/%d",x); ans.pb(buf); if(nr==0) break; int dr = x*d; int g = gcd(nr,dr); n = nr / g; d = dr / g; } } return ans; } };