Hatena::Grouptopcoder

naoya_t@topcoder RSSフィード

2009-01-20

SRM360 Div1 Easy: SumOfSelectedCells

| 00:21 | SRM360 Div1 Easy: SumOfSelectedCells - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM360 Div1 Easy: SumOfSelectedCells - naoya_t@topcoder SRM360 Div1 Easy: SumOfSelectedCells - naoya_t@topcoder のブックマークコメント

これは難しい。むしろ撃墜レースと考えるべき問題。実際Div1でも通過率34%と、500点問題を下回っている。

  • DP的に解こうとしている
  • 数回のsubmit/systestの末、とりあえず以下のコードまで来た
  • まだCase#37がTLE
  • 後で上手な人のコードを見るとしよう
class SumOfSelectedCells {
 public:
  string hypothesis(vector<string> table) {
    int h=sz(table);
    vector<vector<int> > t(h);
    rep(i,h) t[i]=map_atoi(split(table[i]));
    int w=sz(t[0]);
    if(w>h){
      vector<vector<int> > t_(w);
      rep(i,w) t_[i].resize(h);
      rep(i,w) rep(j,h) t_[i][j]=t[j][i];
      t=t_;
      swap(w,h);
    }
    // w<=h

    map<int,int> memo;
    int mmax=1<<h;

    if(w==1){
      int z=t[0][0];
      for(int i=1;i<h;i++) if(z!=t[i][0]) goto incorrect;
      goto correct; //oops
    }
    if(h==2){
      if (t[0][0]+t[1][1] == t[1][0]+t[0][1])
        goto correct;
      else
        goto incorrect;
    }
    // nC2
    rep(x,h) {
      rep(i,h) {
        if(i==x) continue;
        rep(j,h) {
          if(j==x||i>=j) continue; //j>i
          int s_ij=t[i][0]+t[j][1],
              s_ji=t[j][0]+t[i][1];
          if(s_ij!=s_ji) goto incorrect;
          int m=(1<<i)|(1<<j);
          memo[m|(2<<h)]=s_ij;
        }
      }
    }
    if(w==2){
      if(h>w){
        int s=-1;
        tr(memo,it){
          int s_=it->second;
          if(s<0)s=s_;
          else if(s!=s_) goto incorrect;
        }
      }
      goto correct;
    }

    for(int d=3;d<=w;d++){
      int b=d+(h-w);
      rep(m,mmax){
        if(__builtin_popcount(m)!=b) continue;
        int s=-1;
        rep(i,h){
          int x=1<<i;
          if((m&x)==0) continue;
          int m_=m-x;
          if(d==3 && b>3){
            for(int m2=3;m2<mmax;m2++){
              if(__builtin_popcount(m2)!=2) continue;
              if((m_&m2)==m2){ m_=m2; break; }
            }
          }
          int s_=t[i][d-1]+memo[m_|((d-1)<<h)];
          if(s<0) s=s_;
          else if(s!=s_) goto incorrect;
        }
        memo[m|(d<<h)]=s;
      }
    }

 correct:
    return "CORRECT";
 incorrect:
    return "INCORRECT";
  }
};
トラックバック - http://topcoder.g.hatena.ne.jp/n4_t/20090120