<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-10239043</id><updated>2011-07-07T16:06:04.554-07:00</updated><category term='string'/><category term='divide and conquer'/><category term='math'/><category term='jobhunting'/><category term='design patterns'/><category term='disjoint set'/><category term='matrix'/><category term='linear algebra'/><category term='linux programming'/><category term='data structure'/><category term='dp'/><category term='search'/><category term='bit operation'/><category term='graph'/><category term='c++'/><category term='sweeping'/><category term='recursion'/><category term='backtracking'/><title type='text'>greeness notes</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://greeness2008.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>95</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-10239043.post-5515690220424390000</id><published>2009-12-07T16:57:00.000-08:00</published><updated>2009-12-07T23:16:20.552-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>another dp</title><content type='html'>&lt;a href="http://www.topcoder.com/wiki/display/tc/SRM+437"&gt;TheSwap&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;framework for a dp solution&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// memoization unit&lt;br /&gt;int memo[][];&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;&lt;br /&gt;  // reset memo&lt;br /&gt;  memset(memo, 0, sizeof(memo));&lt;br /&gt;&lt;br /&gt;  // calling subroutine to iteratively solve the problem&lt;br /&gt;  return doit();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int doit(int n, int k ) {&lt;br /&gt;  //if already visited state, return memo[][];&lt;br /&gt;  if (memo[][] != 0) return memo[][];&lt;br /&gt;&lt;br /&gt;  // if it is the stopping condition, return memo[] = ? //&lt;br /&gt;  // e.g., k = 0 return n????&lt;br /&gt;&lt;br /&gt;  // initialize return value&lt;br /&gt;  int ret = 0; // -1 sometimes&lt;br /&gt;&lt;br /&gt;  for(all the possible variables) {&lt;br /&gt;    for(for the possible variables) {&lt;br /&gt;&lt;br /&gt;      // pre-processing to get n_1&lt;br /&gt;&lt;br /&gt;      // enter subproblem&lt;br /&gt;      // comparison_funct, e.g., max, min, ++&lt;br /&gt;      // note k-1 below, this identifies the subproblem&lt;br /&gt;      ret = comparison_function(ret, doit(n_1, k-1) ) ; &lt;br /&gt;&lt;br /&gt;      // post-processing to get back n&lt;br /&gt;      // we might need some processing to retrieve n in the original problem &lt;br /&gt;      n = f(n_1);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // this state is visited, set it in the memo&lt;br /&gt;  return ret = memo[][];&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int doit(vector&lt;int&gt; &amp;v, int k) {&lt;br /&gt;  int rv = get_v(v);&lt;br /&gt;&lt;br /&gt;  // visited&lt;br /&gt;  if(memo[rv][k] != 0) return memo[rv][k];&lt;br /&gt;&lt;br /&gt;  if(k == 0) return memo[rv][k] = rv;&lt;br /&gt;&lt;br /&gt;  int a = -1;&lt;br /&gt;  for(int i = 0; i &lt; v.size(); ++i) {&lt;br /&gt;    for(int j = i+1; j &lt; v.size(); ++j) {&lt;br /&gt;&lt;br /&gt;      // excluded cases: highest digit does not swap with '0'&lt;br /&gt;      if (j == v.size()-1 &amp;&amp; v[i] == 0) continue;&lt;br /&gt;&lt;br /&gt;      // pre-processing&lt;br /&gt;      int tmp = v[i];&lt;br /&gt;      v[i] = v[j], v[j] = tmp;&lt;br /&gt;      // enter subproblem&lt;br /&gt;      a = max(a, doit(v, k-1));&lt;br /&gt;&lt;br /&gt;      // post-processing&lt;br /&gt;      v[j] = v[i], v[i] = tmp;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;      &lt;br /&gt;  return memo[rv][k] = a;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For another problem in &lt;a href="http://www.topcoder.com/wiki/display/tc/SRM+454"&gt;NumbersAndMaches&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;const int dis[10][7] =&lt;br /&gt;{&lt;br /&gt;  {1, 1, 1, 0, 1, 1, 1},&lt;br /&gt;  {0, 0, 1, 0, 0, 1, 1},&lt;br /&gt;  {1, 0, 1, 1, 1, 0, 1},&lt;br /&gt;  {1, 0, 1, 1, 0, 1, 1},&lt;br /&gt;  {0, 1, 1, 1, 0, 1, 0},&lt;br /&gt;  {1, 1, 0, 1, 0, 1, 1},&lt;br /&gt;  {1, 1, 0, 1, 1, 1, 1},&lt;br /&gt;  {1, 0, 1, 0, 0, 1, 0},&lt;br /&gt;  {1, 1, 1, 1, 1, 1, 1},&lt;br /&gt;  {1, 1, 1, 1, 0, 1, 1},&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;long long dp[20][127][127];&lt;br /&gt;&lt;br /&gt;int _inc[10][10], _dec[10][10];&lt;br /&gt;&lt;br /&gt;int k;&lt;br /&gt;long long solve(long long N, int idx, int added, int removed) {&lt;br /&gt; &lt;br /&gt;  if (dp[idx][added][removed] != -1) &lt;br /&gt;    return dp[idx][added][removed];&lt;br /&gt;&lt;br /&gt;  if(N == 0) {&lt;br /&gt;    if (added == removed &amp;&amp; added &lt;= k) {&lt;br /&gt;      return 1LL;&lt;br /&gt;    }&lt;br /&gt;    return 0LL;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  int i = N % 10;&lt;br /&gt;  long long ret = 0;&lt;br /&gt;  for(int j = 0; j &lt;= 9; ++j) {&lt;br /&gt;    ret += solve(N/10, idx+1, added + _inc[i][j], removed + _dec[i][j]);&lt;br /&gt;  }&lt;br /&gt;  return dp[idx][added][removed] = ret;&lt;br /&gt;}&lt;br /&gt;  &lt;br /&gt;long long NumbersAndMatches::differentNumbers(long long N, int K)&lt;br /&gt;{&lt;br /&gt;    for (int i = 0; i &lt; 10; i ++)&lt;br /&gt;      for (int j = 0; j &lt; 10; j ++)&lt;br /&gt;      {&lt;br /&gt;        _inc[i][j] = _dec[i][j] = 0;&lt;br /&gt;        for (int k = 0; k &lt; 7; k ++)&lt;br /&gt;        {&lt;br /&gt;          if (dis[i][k] &lt; dis[j][k])&lt;br /&gt;            _inc[i][j] ++;&lt;br /&gt;          if (dis[i][k] &gt; dis[j][k])&lt;br /&gt;            _dec[i][j] ++;&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    k = K;&lt;br /&gt;    memset(dp, -1, sizeof(dp));&lt;br /&gt;    return solve(N, 0, 0, 0);    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-5515690220424390000?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5515690220424390000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5515690220424390000'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2009/12/another-dp.html' title='another dp'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-8036720900466785672</id><published>2009-11-28T20:35:00.000-08:00</published><updated>2009-11-28T20:39:38.476-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>bitset and memoization</title><content type='html'>&lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;pm=10620&amp;rd=13902"&gt;SRM 448 DIVII LEVEL 3&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;http://forums.topcoder.com/?module=Thread&amp;threadID=651040&amp;start=0&lt;br /&gt;&lt;br /&gt;Let D(n,m) = number of ways to arrange the cards given that we have used "m" cards (m = bitmask representation) and the last card that was chosen was card n.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-8036720900466785672?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8036720900466785672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8036720900466785672'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2009/11/bitset-and-memoization.html' title='bitset and memoization'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-976379866133891789</id><published>2009-11-21T14:54:00.000-08:00</published><updated>2009-11-21T14:59:24.498-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='string'/><title type='text'>sscanf</title><content type='html'>to read in the numbers in the following string&lt;br /&gt;&lt;br /&gt;string s = "1000 ml of water, weighing 1000 g"&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int v;&lt;br /&gt;sscanf(s, "%d ml of", &amp;v);&lt;br /&gt;&lt;br /&gt;size_t p = s.find(',');&lt;br /&gt;&lt;br /&gt;int m;&lt;br /&gt;sscanf(s.substr(p+2, s.length()-p).c_str(), "weighing %d", &amp;m);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note: the use of &lt;span style="font-weight:bold;"&gt;c_str()&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;sscanf()&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-976379866133891789?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/976379866133891789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/976379866133891789'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2009/11/sscanf.html' title='sscanf'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1269379623442575841</id><published>2009-11-21T13:23:00.000-08:00</published><updated>2009-11-21T13:27:20.843-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='string'/><title type='text'>STL comparison FUNCTOR</title><content type='html'>&lt;a href="http://www.topcoder.com/tc?module=Static&amp;d1=match_editorials&amp;d2=srm374"&gt;http://www.topcoder.com/tc?module=Static&amp;d1=match_editorials&amp;d2=srm374&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &lt; iostream &gt;&lt;br /&gt;#include &lt; vector &gt;&lt;br /&gt;#include &lt; string &gt;&lt;br /&gt;#include &lt; algorithm &gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;bool isvowl(char c) {&lt;br /&gt;  if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u')&lt;br /&gt;    return true;&lt;br /&gt;  return false;&lt;br /&gt;  &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;struct word {&lt;br /&gt;  string w;&lt;br /&gt;  vector&lt;string&gt; s1; //sorted&lt;br /&gt;  vector&lt;string&gt; s2; //unsorted&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// comparison function&lt;br /&gt;bool operator &lt; (const word &amp;a, const word &amp;b) {&lt;br /&gt;  if (a.s1 != b.s1) return a.s1 &lt; b.s1;&lt;br /&gt;  return a.s2 &lt; b.s2;&lt;br /&gt;}  &lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;class SyllableSorting {&lt;br /&gt;public:&lt;br /&gt;  &lt;br /&gt;  vector &lt;string&gt; sortWords(vector &lt;string&gt; words) {&lt;br /&gt;    &lt;br /&gt;    vector&lt;word&gt; vw;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    for(int i = 0; i &lt; words.size(); ++i) {&lt;br /&gt;    &lt;br /&gt;      vector&lt;string&gt; syl;&lt;br /&gt;      word W;&lt;br /&gt;          &lt;br /&gt;      string s("");&lt;br /&gt;      s += words[i][0];&lt;br /&gt;          &lt;br /&gt;      for (int j = 1; j &lt; words[i].length(); ++j) {&lt;br /&gt;        char c = words[i][j];&lt;br /&gt;        bool pv = isvowl(words[i][j-1]);&lt;br /&gt;        bool v  = isvowl(c);&lt;br /&gt;        if (pv) { //previous char is a vowl&lt;br /&gt;          if (v)&lt;br /&gt;            s += c;&lt;br /&gt;          else {&lt;br /&gt;            syl.push_back(s);&lt;br /&gt;            s = c;&lt;br /&gt;          }&lt;br /&gt;        } else {  // previous char is a consonant&lt;br /&gt;          s += c;&lt;br /&gt;        } &lt;br /&gt;      }&lt;br /&gt;      syl.push_back(s);&lt;br /&gt;      &lt;br /&gt;      for(int k = 0; k &lt; syl.size(); ++k)&lt;br /&gt;        cout &lt;&lt; syl[k] &lt;&lt; "  ";&lt;br /&gt;      cout &lt;&lt; endl;&lt;br /&gt;      &lt;br /&gt;      W.w = words[i];&lt;br /&gt;      &lt;br /&gt;      W.s2 = (syl);&lt;br /&gt;      &lt;br /&gt;      sort(syl.begin(), syl.end());&lt;br /&gt;      &lt;br /&gt;      W.s1 = (syl);&lt;br /&gt;           &lt;br /&gt;      vw.push_back(W);&lt;br /&gt;    &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    sort(vw.begin(), vw.end());&lt;br /&gt;    vector&lt;string&gt; ret;&lt;br /&gt;    for(int i = 0; i &lt; vw.size(); ++i)&lt;br /&gt;      ret.push_back(vw[i].w);&lt;br /&gt;    return ret;&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1269379623442575841?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1269379623442575841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1269379623442575841'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2009/11/stl-comparison-functor.html' title='STL comparison FUNCTOR'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-7747330070221431859</id><published>2009-11-18T18:57:00.000-08:00</published><updated>2009-11-18T21:09:18.864-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>Coin toss and Absorbing Markov Chain</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_52n3nML4Mbo/SwS7s99YnaI/AAAAAAAAETc/-evZ9RRuZX0/s1600/coin.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 112px;" src="http://2.bp.blogspot.com/_52n3nML4Mbo/SwS7s99YnaI/AAAAAAAAETc/-evZ9RRuZX0/s320/coin.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5405651833972104610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.mitbbs.com/mitbbs_bbsdoc_div_article.php?board=Quant&amp;gid=31212871"&gt;http://www.mitbbs.com/mitbbs_bbsdoc_div_article.php?board=Quant&amp;gid=31212871&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A fair coin is flipped until the first time one of the following two&lt;br /&gt;patterns appeared: TTH or HTH&lt;br /&gt;ask: which one you should choose for a better chance to win&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;+ TT = .5 TTH + .5 TT&lt;br /&gt;| HT = .5 HTH + .5 TT&lt;br /&gt;| T  = .5 TT  + .5 H&lt;br /&gt;| H  = .5 HT  + .5 H&lt;br /&gt;+ S  = .5 T   + .5 H&lt;br /&gt;&lt;br /&gt;If we let TTH = 1 and HTH = 0, we finally get S = 5/8 (the probability of reaching TTH first)&lt;br /&gt;or otherwise&lt;br /&gt;   we let HTH = 1 and TTH = 0, we finally get S = 3/8 (the probability of reaching HTH first)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We start from the definition of Absorbing Markov Chain.&lt;br /&gt;REF: Chap 11, Markov Chains, from www.dartmouth.edu/~chance/teaching&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A state s_i of a Markov chain is called &lt;span style="font-style:italic;"&gt;absorbing&lt;/span&gt; if it is impossible to leave it (i.e., p_ii = 1). A Markov chain is absorbing if it has at lease one absorbing state, and if from every state it is possible to go to an absorbing state (not necessarily in one step). The state that is not absorbing is called &lt;span style="font-style:italic;"&gt;transient&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;The interesting questions about an absorbing Markov chain are:&lt;br /&gt;&lt;br /&gt;- What is the probability that the process will eventually reach a given absorbing state?&lt;br /&gt;- On the average, how long will it take for the process to be absorbed?&lt;br /&gt;- On the average, how many times will the process be in each transient state?&lt;br /&gt;&lt;br /&gt;In general, the answers to all questions depends on &lt;br /&gt;- the state from which the process starts&lt;br /&gt;- the transition probabilities.&lt;br /&gt;The answers to the above questions are the theorems listed below. &lt;br /&gt;&lt;br /&gt;We first write the transition matrix in canonical Form by explicitly write Q and R. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;      TT           T         S         H         HT&lt;br /&gt;Q =&lt;br /&gt;&lt;br /&gt;TT    0.5000         0         0         0         0&lt;br /&gt; T    0.5000         0         0    0.5000         0&lt;br /&gt; S         0    0.5000         0    0.5000         0&lt;br /&gt; H         0         0         0    0.5000    0.5000&lt;br /&gt;HT    0.5000         0         0         0         0&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;       TTH       HTH&lt;br /&gt;R =   &lt;br /&gt;&lt;br /&gt;TT    0.5000         0&lt;br /&gt; T         0         0&lt;br /&gt; S         0         0&lt;br /&gt; H         0         0&lt;br /&gt;HT         0    0.5000&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Theorem&lt;/span&gt;: For an absorbing Markov chain the matrix I-Q has an inverse N = I + Q + Q^2 + ....  The ij-entry of the matrix N is the expected number of times the chain is in state s_j, given that it starts in state s_i. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; N = inv(eye(5)-Q)&lt;br /&gt;&lt;br /&gt;N =&lt;br /&gt;&lt;br /&gt;    2.0000         0         0         0         0&lt;br /&gt;    1.5000    1.0000         0    1.0000    0.5000&lt;br /&gt;    1.2500    0.5000    1.0000    1.5000    0.7500&lt;br /&gt;    1.0000         0         0    2.0000    1.0000&lt;br /&gt;    1.0000         0         0         0    1.0000&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By reading the first line of N, we know that starting from TT, the expected number of times we still in TT is 2. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Theorem&lt;/span&gt;: The sum of row i of N is the expected number of steps before the chain is absorbed given that the chain starts in state s_i.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&gt;&gt; t = N*ones(5,1)&lt;br /&gt;&lt;br /&gt;t =&lt;br /&gt;&lt;br /&gt;     2&lt;br /&gt;     4&lt;br /&gt;     5&lt;br /&gt;     4&lt;br /&gt;     2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So starting from S, the expected number of steps before absorbing in either TTH or HTH is 5. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Theorem&lt;/span&gt;: Let b_ij be the probability that an absorbing chain will be absorbed in the absorbing state s_j if it starts in the transient state s_i. Let B be the matrix with entries b_ij. Then B is an txr matrix, and &lt;br /&gt;&lt;br /&gt;B = NR, &lt;br /&gt;&lt;br /&gt;where N is the fundamental matrix and R is as in the canonical form. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; B = N*R&lt;br /&gt;&lt;br /&gt;B =&lt;br /&gt;&lt;br /&gt;    1.0000         0&lt;br /&gt;    0.7500    0.2500&lt;br /&gt;    0.6250    0.3750&lt;br /&gt;    0.5000    0.5000&lt;br /&gt;    0.5000    0.5000&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Thus starting from S, we have probability of 0.625 = 5/8 to be absorbed into state TTH and probability of 0.375 = 3/8 to be absorbed into state HTH.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now let us consider adding another absorbing state THT. The transition graph is as below:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_52n3nML4Mbo/SwTQeK88xdI/AAAAAAAAETk/FGclfwsp92g/s1600/markov.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 130px;" src="http://3.bp.blogspot.com/_52n3nML4Mbo/SwTQeK88xdI/AAAAAAAAETk/FGclfwsp92g/s400/markov.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5405674669506086354" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Q =      S         T         H        TH        HT        TT&lt;br /&gt;&lt;br /&gt;         0    0.5000    0.5000         0         0         0     S&lt;br /&gt;         0         0         0    0.5000         0    0.5000     T&lt;br /&gt;         0         0    0.5000         0    0.5000         0     H&lt;br /&gt;         0         0    0.5000         0         0         0     TH&lt;br /&gt;         0         0         0         0         0    0.5000     HT&lt;br /&gt;         0         0         0         0         0    0.5000     TT&lt;br /&gt;&lt;br /&gt;R =    THT       HTH       TTH&lt;br /&gt;&lt;br /&gt;         0         0         0  S&lt;br /&gt;         0         0         0  T&lt;br /&gt;         0         0         0  H&lt;br /&gt;    0.5000         0         0  TH&lt;br /&gt;         0    0.5000         0  HT&lt;br /&gt;         0         0    0.5000  TT&lt;br /&gt;&lt;br /&gt;&gt;&gt; N = inv(eye(6)-Q)&lt;br /&gt;&lt;br /&gt;N =&lt;br /&gt;&lt;br /&gt;    1.0000    0.5000    1.2500    0.2500    0.6250    1.1250&lt;br /&gt;         0    1.0000    0.5000    0.5000    0.2500    1.2500&lt;br /&gt;         0         0    2.0000         0    1.0000    1.0000&lt;br /&gt;         0         0    1.0000    1.0000    0.5000    0.5000&lt;br /&gt;         0         0         0         0    1.0000    1.0000&lt;br /&gt;         0         0         0         0         0    2.0000&lt;br /&gt;&lt;br /&gt;&gt;&gt; N*ones(6,1)&lt;br /&gt;&lt;br /&gt;ans =&lt;br /&gt;&lt;br /&gt;    4.7500 S&lt;br /&gt;    3.5000 T&lt;br /&gt;    4.0000 H&lt;br /&gt;    3.0000 TH&lt;br /&gt;    2.0000 HT&lt;br /&gt;    2.0000 TT&lt;br /&gt;&lt;br /&gt;&gt;&gt; B = N*R&lt;br /&gt;&lt;br /&gt;B =    THT       HTH       TTH&lt;br /&gt;&lt;br /&gt;    0.1250    0.3125    0.5625  S&lt;br /&gt;    0.2500    0.1250    0.6250  T&lt;br /&gt;         0    0.5000    0.5000  H&lt;br /&gt;    0.5000    0.2500    0.2500  TH&lt;br /&gt;         0    0.5000    0.5000  HT&lt;br /&gt;         0         0    1.0000  TT&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-7747330070221431859?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/7747330070221431859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/7747330070221431859'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2009/11/coin-toss-and-absorbing-markov-chain.html' title='Coin toss and Absorbing Markov Chain'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_52n3nML4Mbo/SwS7s99YnaI/AAAAAAAAETc/-evZ9RRuZX0/s72-c/coin.JPG' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-5684989163010315664</id><published>2009-02-24T19:23:00.000-08:00</published><updated>2009-02-24T19:26:05.070-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>protected data or private data</title><content type='html'>http://www.parashift.com/c++-faq-lite/basics-of-inheritance.html&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here's the way I say it: if I expect derived classes, I should ask this question: who will create them?  If the people who will create them will be outside your team, or if there are a &lt;em&gt;huge&lt;/em&gt; number of derived classes, then and only then is it worth creating a protected interface and using private data.  If I expect the derived classes to be created by my own team and to be reasonable in number, it's just not worth the trouble: use protected data.  And hold your head up, don't be ashamed: it's the &lt;em&gt;right thing&lt;/em&gt; to do! &lt;/p&gt;&lt;p&gt;The benefit of protected access functions is that you won't break your derived classes as often as you would if your data was protected.  Put it this way: if you believe your users will be outside your team, you should do a lot more than just provide get/set methods for your private data.  You should actually create another interface.  You have a public interface for one set of users, and a protected interface for another set of users.  But they both need an interface that is carefully designed — designed for stability, usability, performance, etc.  And at the end of the day, the real benefit of privatizing your data (including providing an interface that is coherent and, as much as possible, opaque) is to avoid breaking your derived classes when you change that data structure. &lt;/p&gt;&lt;p&gt;But if your own team is creating the derived classes, and there are a reasonably small number of them, it's simply not worth the effort: use protected data.  Some purists (translation: people who've never stepped foot in the real world, people who've spent their entire lives in an ivory tower, people who don't understand words like "customer" or "schedule" or "deadline" or "ROI") think that &lt;em&gt;everything&lt;/em&gt; ought to be reusable and &lt;em&gt;everything&lt;/em&gt; ought to have a clean, easy to use interface.  Those kinds of people are dangerous: they often make your project late, since they make everything equally important.  They're basically saying, "We have 100 tasks, and I have carefully prioritized them: they are all priority 1." They make the notion of priority meaningless. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-5684989163010315664?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5684989163010315664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5684989163010315664'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2009/02/protected-data-or-private-data.html' title='protected data or private data'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-4983773639634084213</id><published>2008-11-15T19:23:00.001-08:00</published><updated>2008-11-15T19:23:30.128-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='recursion'/><title type='text'>Repeated Squaring</title><content type='html'>&lt;p&gt;&lt;a title="http://www.algorithmist.com/index.php/Repeated_Squaring" href="http://www.algorithmist.com/index.php/Repeated_Squaring"&gt;http://www.algorithmist.com/index.php/Repeated_Squaring&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Repeated squaring, or repeated doubling is an algorithm that computes integer powers of a number quickly. The general problem is to compute xy for an arbitrary integer y.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// Calculates n to the p power, where p is a positive number.&lt;/span&gt;&lt;br /&gt;func power( var n as integer, var p as integer )&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; p = 0 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 1&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; p = 1 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; n&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; p is odd&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; n * power( n * n, (p-1) / 2 )&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; power( n * n, p / 2 )&lt;br /&gt;end func&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-4983773639634084213?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4983773639634084213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4983773639634084213'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/repeated-squaring.html' title='Repeated Squaring'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2389463035652958441</id><published>2008-11-11T21:00:00.000-08:00</published><updated>2008-11-11T23:04:13.735-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='recursion'/><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><title type='text'>quadtree</title><content type='html'>&lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/Quadtree" href="http://en.wikipedia.org/wiki/Quadtree"&gt;http://en.wikipedia.org/wiki/Quadtree&lt;/a&gt;&lt;/p&gt; &lt;p&gt;UVa problem: 297: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;page=show_problem&amp;amp;category=4&amp;amp;problem=233&amp;amp;mosmsg=Submission+received+with+ID+6792339"&gt;Quadtrees&lt;/a&gt;&lt;/p&gt; &lt;p&gt;refer to forum: &lt;a title="http://acm.uva.es/board/viewtopic.php?f=2&amp;amp;t=700&amp;amp;p=2691&amp;amp;hilit=297&amp;amp;sid=156699fafa75aaeacf281e1af3a8006c#p2691" href="http://acm.uva.es/board/viewtopic.php?f=2&amp;amp;t=700&amp;amp;p=2691&amp;amp;hilit=297&amp;amp;sid=156699fafa75aaeacf281e1af3a8006c#p2691"&gt;http://acm.uva.es/board/viewtopic.php?f=2&amp;amp;t=700&amp;amp;p=2691&amp;amp;hilit=297&amp;amp;sid=156699fafa75aaeacf281e1af3a8006c#p2691&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;br /&gt;#define M 32&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p[M];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; idx;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; mask[] = {&lt;br /&gt;  0, 0x1, 0x3, 0, &lt;span style="color: #008000"&gt;// 0-3&lt;/span&gt;&lt;br /&gt;  0xf, 0, 0, 0, 0xff, &lt;span style="color: #008000"&gt;//4-8&lt;/span&gt;&lt;br /&gt;  0,0,0,0,0,0,0,0xffff, &lt;span style="color: #008000"&gt;// 16&lt;/span&gt;&lt;br /&gt;  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xffffffff &lt;span style="color: #008000"&gt;// 32&lt;/span&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#ifndef ONLINE_JUDGE&lt;br /&gt;&lt;span style="color: #008000"&gt;// couting 1's&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; count_bit(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; bits = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(n) {&lt;br /&gt;        n &amp;amp;= n-1;&lt;br /&gt;        ++bits;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; bits;&lt;br /&gt;}&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; color (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *str, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; size, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y) {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (str[idx] == 'p') {&lt;br /&gt;    idx ++;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; sz = size&amp;gt;&amp;gt;1;&lt;br /&gt;    color(str, sz, x+sz, y);&lt;br /&gt;    color(str, sz, x, y);&lt;br /&gt;    color(str, sz, x, y+sz);&lt;br /&gt;    color(str, sz, x+sz, y+sz);&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (str[idx] == 'f') {&lt;br /&gt;    idx ++;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = y; i &amp;lt; y + size; i ++)&lt;br /&gt;      p[i] |= mask[size] &amp;lt;&amp;lt; x;&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; idx++;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main () {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; num;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; tree1[1500], tree2[1500];&lt;br /&gt;&lt;br /&gt;  scanf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", &amp;amp;num);&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(num--) {&lt;br /&gt;    scanf("&lt;span style="color: #8b0000"&gt;%s\n%s\n&lt;/span&gt;", tree1, tree2);&lt;br /&gt;&lt;br /&gt;    memset(p, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(p));&lt;br /&gt;&lt;br /&gt;    idx=0;&lt;br /&gt;    color(tree1, M, 0, 0);&lt;br /&gt;&lt;br /&gt;    idx=0;&lt;br /&gt;    color(tree2, M, 0, 0);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; total = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; M; i ++)&lt;br /&gt;#ifndef ONLINE_JUDGE&lt;br /&gt;      total += count_bit(p[i]);&lt;br /&gt;#&lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;      total += __builtin_popcount(p[i]);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;There are %d black pixels.\n&lt;/span&gt;", total);&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;/pre&gt;&lt;pre&gt;UVa problem: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;category=9&amp;amp;page=show_problem&amp;amp;problem=693"&gt;752 - Unscrambling Images&lt;/a&gt;&lt;/pre&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;deque&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; q[16][16];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; e[16][16]; &lt;span style="color: #008000"&gt;// encrypted&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; d[16][16]; &lt;span style="color: #008000"&gt;// decoded&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; getxy(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; size, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &amp;amp;x, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &amp;amp;y) {&lt;br /&gt;&lt;br /&gt;  deque&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; Q;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(k &amp;gt; 0) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; r = k % 4;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (r == 0) {&lt;br /&gt;      r = 4;&lt;br /&gt;      k = (k-4) &amp;gt;&amp;gt; 2;&lt;br /&gt;    } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;      k = k &amp;gt;&amp;gt;2;&lt;br /&gt;&lt;br /&gt;    Q.push_front(r);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  x = 0, y = 0;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; Q.size(); ++i) {&lt;br /&gt;    size = size &amp;gt;&amp;gt; 1;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; idx = Q[i];&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (idx == 2)&lt;br /&gt;      y += size;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (idx == 3)&lt;br /&gt;      x += size;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (idx == 4) {&lt;br /&gt;      x += size;&lt;br /&gt;      y += size;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; size;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ndata;&lt;br /&gt;  scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;ndata);&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nd = 1;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(nd &amp;lt;= ndata) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(nd &amp;gt; 1) printf("&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;");&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;Case %d\n\n&lt;/span&gt;", nd++);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n;&lt;br /&gt;    scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;n);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// quadtree reset to all 0&lt;/span&gt;&lt;br /&gt;    memset(q, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(q));&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m; &lt;span style="color: #008000"&gt;// number of leaf nodes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;m); &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; intensity;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m; ++ i) {&lt;br /&gt;      scanf("&lt;span style="color: #8b0000"&gt;%d %d &lt;/span&gt;", &amp;amp;k, &amp;amp;intensity);&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x, y;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; size = getxy(n, k, x, y);&lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = x; i &amp;lt; x+size; ++i)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = y;j &amp;lt; y+size; ++j)&lt;br /&gt;          q[i][j] = intensity;      &lt;br /&gt;    }&lt;br /&gt;&lt;span style="color: #008000"&gt;/*&lt;br /&gt;    for(int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;      for(int j = 0; j &amp;lt; n; ++j)&lt;br /&gt;        printf("%4d", q[i][j]);&lt;br /&gt;      printf("\n");&lt;br /&gt;    }&lt;br /&gt;    printf("\n");&lt;br /&gt;*/&lt;/span&gt;&lt;br /&gt;    scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;m);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// encrypted quadtree reset to all 0&lt;/span&gt;&lt;br /&gt;    memset(e, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(e));&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m; ++ i) {&lt;br /&gt;      scanf("&lt;span style="color: #8b0000"&gt;%d %d &lt;/span&gt;", &amp;amp;k, &amp;amp;intensity);&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x, y;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; size = getxy(n, k, x, y);&lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = x; i &amp;lt; x+size; ++i)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = y;j &amp;lt; y+size; ++j)&lt;br /&gt;          e[i][j] = intensity;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; n; ++j) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x = q[i][j] / n;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y = q[i][j] % n;&lt;br /&gt;        d[x][y] = e[i][j];&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; n; ++j)&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt;%4d&lt;/span&gt;", d[i][j]);&lt;br /&gt;      printf("&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;");&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2389463035652958441?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2389463035652958441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2389463035652958441'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/quadtree.html' title='quadtree'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-989144062490288471</id><published>2008-11-05T12:10:00.001-08:00</published><updated>2008-11-11T21:09:10.021-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='recursion'/><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><title type='text'>Add without +</title><content type='html'>&lt;p&gt;Write a program to add two numbers a and b.&lt;br&gt;1. Without Using + operator&lt;br&gt;2. Without using any loops  &lt;p&gt;Sum = A XOR B&lt;br&gt;Carry = A AND B  &lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; add(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; q)&lt;br /&gt;{&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(q == 0)&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; p;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k, r;&lt;br /&gt;  k = p ^ q;&lt;br /&gt;  r = p &amp;amp; q;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; add(k, r&amp;lt;&amp;lt;1); &lt;span style="color: #008000"&gt;// carry left shift 1 bit&lt;/span&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;  printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", add(4,7));&lt;br /&gt;  printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", add(401,7));&lt;br /&gt;  printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", add(14,7));&lt;br /&gt;  printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", add(4,47));&lt;br /&gt;  printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", add(4,-97));&lt;br /&gt;  printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", add(-4,-97));&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;output:&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;11&lt;br&gt;408&lt;br&gt;21&lt;br&gt;51&lt;br&gt;-93&lt;br&gt;-101&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-989144062490288471?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/989144062490288471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/989144062490288471'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/add-without.html' title='Add without +'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-8592727578205521713</id><published>2008-11-05T12:08:00.001-08:00</published><updated>2008-11-05T13:39:15.824-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>C++ notes II</title><content type='html'>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Segmentation_fault"&gt;Segmentation fault&lt;/a&gt;:&amp;nbsp; A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed. &lt;a href="http://en.wikipedia.org/wiki/Segmentation_%28memory%29"&gt;Segmentation&lt;/a&gt; is one approach to &lt;a href="http://en.wikipedia.org/wiki/Memory_management"&gt;memory management&lt;/a&gt; and protection in the &lt;a href="http://en.wikipedia.org/wiki/Operating_system"&gt;operating system&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/Stack_buffer_overflow" href="http://en.wikipedia.org/wiki/Stack_buffer_overflow"&gt;Stack Overflow&lt;/a&gt;: Stack buffer overflow bugs are caused when a program writes more data to a buffer located on the stack than there was actually allocated for that buffer. This almost always results in corruption of adjacent data on the stack, and in cases where the overflow was triggered by mistake, will often cause the program to crash or operate incorrectly.&lt;/p&gt; &lt;p&gt;A &lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Core_dump"&gt;core dump&lt;/a&gt;&lt;/b&gt; is the recorded state of the working &lt;a href="http://en.wikipedia.org/wiki/Computer_storage"&gt;memory&lt;/a&gt; of a &lt;a href="http://en.wikipedia.org/wiki/Computer_program"&gt;computer program&lt;/a&gt; at a specific time, generally when the program has terminated abnormally (&lt;a href="http://en.wikipedia.org/wiki/Crash_%28computing%29"&gt;crashed&lt;/a&gt;).&lt;sup&gt; &lt;/sup&gt;In practice, other key pieces of &lt;a href="http://en.wikipedia.org/wiki/Context_switch"&gt;program state&lt;/a&gt; are usually dumped at the same time, including the &lt;a href="http://en.wikipedia.org/wiki/Processor_register"&gt;processor registers&lt;/a&gt;, which may include the program counter and stack pointer, memory management information, and other processor and operating system flags and information.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.codersource.net/cpp_tutorial_static_functions.html"&gt;Static function&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;The differences between a static member function and non-static member functions are as follows.  &lt;ul&gt; &lt;li&gt;A static member function can access only static member data, static member functions and data and functions outside the class. A non-static member function can access all of the above including the static data member.  &lt;li&gt;A static member function can be called, even when a class is not instantiated, a non-static member function can be called only after instantiating the class as an object.  &lt;li&gt;A static member function cannot be declared virtual, whereas a non-static member functions can be declared as virtual  &lt;li&gt;A static member function cannot have access to the 'this' pointer of the class.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The static member functions are not used very frequently in programs. But nevertheless, they become useful whenever we need to have functions which are accessible even when the class is not instantiated. &lt;/p&gt; &lt;p&gt;A &lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Memory_leak"&gt;memory leak&lt;/a&gt;&lt;/b&gt; is a particular type of unintentional memory consumption by a &lt;a href="http://en.wikipedia.org/wiki/Computer_program"&gt;computer program&lt;/a&gt; where the program fails to release &lt;a href="http://en.wikipedia.org/wiki/Dynamic_memory"&gt;memory&lt;/a&gt; when no longer needed. This condition is normally the result of a bug in a program that prevents it from freeing up memory that it no longer needs.&lt;/p&gt; &lt;p&gt;&lt;a title="http://linux.die.net/man/2/fork" href="http://linux.die.net/man/2/fork"&gt;http://linux.die.net/man/2/fork&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;fork&lt;/b&gt;() creates a child process that differs from the parent process only in its PID and PPID, and in the fact that resource utilizations are set to 0. File locks and pending signals are not inherited.  &lt;p&gt;Under Linux, &lt;b&gt;fork&lt;/b&gt;() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child.  &lt;h4&gt;Return Value&lt;/h4&gt; &lt;p&gt;On success, the PID of the child process is returned in the parent's thread of execution, and a 0 is returned in the child's thread of execution. On failure, a -1 will be returned in the parent's context, no child process will be created, and &lt;i&gt;errno&lt;/i&gt; will be set appropriately.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.fredosaurus.com/notes-cpp/oop-condestructors/shallowdeepcopy.html"&gt;Shallow copies and deep copies&lt;/a&gt;&lt;/p&gt; &lt;p&gt;A &lt;i&gt;shallow copy&lt;/i&gt; of an object copies all of the member field values. This works well if the fields are values, but may not be what you want for fields that point to dynamically allocated memory. The pointer will be copied. but the memory it points to will not be copied -- the field in both the original object and the copy will then point to the same dynamically allocated memory, which is not usually what you want. The default copy constructor and assignment operator make shallow copies.  &lt;p&gt;A &lt;i&gt;deep copy&lt;/i&gt; copies all fields, &lt;i&gt;and&lt;/i&gt; makes copies of dynamically allocated memory pointed to by the fields. To make a deep copy, you must write a copy constructor and overload the assignment operator, otherwise the copy will point to the original, with disasterous consequences.  &lt;h4&gt;Deep copies need ...&lt;/h4&gt; &lt;p&gt;If an object has pointers to dynamically allocated memory, and the dynamically allocated memory needs to be copied when the original object is copied, then a deep copy is required.  &lt;p&gt;A class that requires deep copies generally needs:  &lt;ul&gt; &lt;li&gt;A &lt;a href="http://www.fredosaurus.com/notes-cpp/oop-condestructors/constructors.html"&gt;constructor&lt;/a&gt; to either make an initial allocation or set the pointer to NULL.  &lt;li&gt;A &lt;a href="http://www.fredosaurus.com/notes-cpp/oop-condestructors/destructors.html"&gt;destructor&lt;/a&gt; to delete the dynamically allocated memory.  &lt;li&gt;A &lt;a href="http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html"&gt;copy constructor&lt;/a&gt; to make a copy of the dynamically allocated memory.  &lt;li&gt;An &lt;a href="http://www.fredosaurus.com/notes-cpp/oop-overloading/overloadassign.html"&gt;overloaded assignment operator&lt;/a&gt; to make a copy of the dynamically allocated memory. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://kenno.wordpress.com/2007/04/04/how-to-kill-defunct-process/"&gt;Defunct Process&lt;/a&gt;:&amp;nbsp; Defunct processes are corrupted processes that can no longer communicate between the parent and child one. Sometimes, they become “zombies” and remain in your system until you reboot your machine. You can try to apply “kill -9″ command, but most of the time you’ll be out of luck.&lt;/p&gt; &lt;p&gt;&lt;a href="http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/cplr155.htm"&gt;Stack unwinding&lt;/a&gt;: &lt;/p&gt; &lt;p&gt;When an exception is thrown and control passes from a try block to a handler, the C++ run time calls destructors for all automatic objects constructed since the beginning of the try block. This process is called &lt;em&gt;stack unwinding&lt;/em&gt;.&lt;a name="idx1364"&gt;&lt;/a&gt; The automatic objects are destroyed in reverse order of their construction. (Automatic objects are local objects that have been declared &lt;tt&gt;auto&lt;/tt&gt; or &lt;tt&gt;register&lt;/tt&gt;, or not declared &lt;tt&gt;static&lt;/tt&gt; or &lt;tt&gt;extern&lt;/tt&gt;. An automatic object &lt;tt&gt;x&lt;/tt&gt; is deleted whenever the program exits the block in which &lt;tt&gt;x&lt;/tt&gt; is declared.) &lt;p&gt;If an exception is thrown during construction of an object consisting of subobjects or array elements, destructors are only called for those subobjects or array elements successfully constructed before the exception was thrown. A destructor for a local static object will only be called if the object was successfully constructed. &lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/Data_segment" href="http://en.wikipedia.org/wiki/Data_segment"&gt;http://en.wikipedia.org/wiki/Data_segment&lt;/a&gt; &lt;p&gt;In the PC architecture there are four basic read-write memory regions in a program: Stack, Data, BSS, and Heap.  &lt;ol&gt; &lt;li&gt;The Data segment contains constants used by the program that are not initialized to zero. For instance the string defined by &lt;code&gt;char s[] = "hello world";&lt;/code&gt; in C would exist in the data part.  &lt;li&gt;The &lt;a href="http://en.wikipedia.org/wiki/.bss"&gt;BSS segment&lt;/a&gt; starts at the end of the data segment and contains all global variables that are initialized to zero. For instance a variable declared &lt;code&gt;static int i;&lt;/code&gt; would be contained in the BSS segment.  &lt;li&gt;The &lt;a href="http://en.wikipedia.org/w/index.php?title=Heap_area&amp;amp;action=edit&amp;amp;redlink=1"&gt;heap area&lt;/a&gt; begins at the end of the data segment and grows to larger addresses from there. The Heap area is managed by &lt;a href="http://en.wikipedia.org/wiki/Malloc"&gt;malloc&lt;/a&gt;, realloc, and free, which use the brk and sbrk system calls to adjust its size. The Heap area is shared by all shared libraries and dynamic load modules in a process.  &lt;li&gt;The &lt;a href="http://en.wikipedia.org/wiki/Stack_%28data_structure%29"&gt;stack&lt;/a&gt; is a LIFO structure, typically located in the higher parts of memory. It usually "grows down" with every register, immediate value or stack frame being added to it. A stack frame consists at minimum of a return address. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;a href="http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/"&gt;Virtual Table&lt;/a&gt; The &lt;strong&gt;virtual table&lt;/strong&gt; is a lookup table of functions used to resolve function calls in a dynamic/late binding manner.&lt;/p&gt; &lt;p&gt;A Simple Garbage Collector for C++&amp;nbsp; &lt;a title="http://www.devarticles.com/c/a/Cplusplus/A-Simple-Garbage-Collector-for-C-plus-plus/" href="http://www.devarticles.com/c/a/Cplusplus/A-Simple-Garbage-Collector-for-C-plus-plus/"&gt;http://www.devarticles.com/c/a/Cplusplus/A-Simple-Garbage-Collector-for-C-plus-plus/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;A &lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Deadlock"&gt;deadlock&lt;/a&gt;&lt;/b&gt; is a situation wherein two or more competing actions are waiting for the other to finish, and thus neither ever does.&lt;/p&gt; &lt;p&gt;In &lt;a href="http://en.wikipedia.org/wiki/Scheduling_%28computing%29"&gt;scheduling&lt;/a&gt;, &lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Priority_inversion"&gt;priority inversion&lt;/a&gt;&lt;/b&gt; is the scenario where a low priority &lt;a href="http://en.wikipedia.org/wiki/Task"&gt;task&lt;/a&gt; holds a shared &lt;a href="http://en.wikipedia.org/wiki/Resource_%28computer_science%29"&gt;resource&lt;/a&gt; that is required by a high priority task. This causes the execution of the high priority task to be blocked until the low priority task has released the resource, effectively "inverting" the relative priorities of the two tasks. If some other medium priority task, one that does not depend on the shared resource, attempts to run in the interim, it will take precedence over both the low priority task &lt;i&gt;and&lt;/i&gt; the high priority task.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-8592727578205521713?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8592727578205521713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8592727578205521713'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/c-notes-ii.html' title='C++ notes II'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-6258629319486706881</id><published>2008-11-05T10:56:00.001-08:00</published><updated>2008-11-05T10:56:04.311-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='search'/><title type='text'>3Sum problem</title><content type='html'>&lt;p&gt;&lt;a title="http://discuss.techinterview.org/default.asp?interview.11.613896.3" href="http://discuss.techinterview.org/default.asp?interview.11.613896.3"&gt;http://discuss.techinterview.org/default.asp?interview.11.613896.3&lt;/a&gt; &lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/3SUM" href="http://en.wikipedia.org/wiki/3SUM"&gt;http://en.wikipedia.org/wiki/3SUM&lt;/a&gt; &lt;p&gt;Given an unsorted array of integers. Find any three numbers satisfying following condition:&lt;br&gt;c = a+b &lt;p&gt;First, sort the array in O(nlogn).&lt;br&gt;For each element c of the array try to find two numbers a and b such that a+b = c.&lt;br&gt;Time complexity:&lt;br&gt;O(n) to find a+b = c in sorted array.&amp;nbsp; (We can use two pointers and move them towards the middle)&lt;/p&gt; &lt;p&gt;Since we do this for each element. O(n^2).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-6258629319486706881?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/6258629319486706881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/6258629319486706881'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/3sum-problem.html' title='3Sum problem'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1035728633202707148</id><published>2008-11-03T22:18:00.001-08:00</published><updated>2008-11-04T20:34:31.670-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><title type='text'>Maximun Flow</title><content type='html'>&lt;p&gt;Residual network: (credit: &lt;a title="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=maxFlow" href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=maxFlow"&gt;http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=maxFlow&lt;/a&gt;)&lt;/p&gt; &lt;ul&gt; &lt;li&gt;if the flow along the edge x-y is less than the capacity there is a &lt;strong&gt;forward edge&lt;/strong&gt; x-y with a capacity equal to the difference between the capacity and the flow (this is called the residual capacity), &lt;/li&gt; &lt;li&gt;if the flow is positive there is a &lt;strong&gt;backward edge&lt;/strong&gt; y-x with a capacity equal to the flow on x-y.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_52n3nML4Mbo/SQ_pHRiP6ZI/AAAAAAAAB9E/7WjqQplHuR0/image%5B8%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="265" alt="image" src="http://lh4.ggpht.com/_52n3nML4Mbo/SQ_pHqwCNpI/AAAAAAAAB9I/-0Fjmr00WCg/image_thumb%5B4%5D.png" width="409" border="0"&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/_52n3nML4Mbo/SQ_pKTRJIUI/AAAAAAAAB9Q/MDve7R-lWNc/image%5B6%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="266" alt="image" src="http://lh5.ggpht.com/_52n3nML4Mbo/SQ_pKqmvZ8I/AAAAAAAAB9U/bTwHfzozzOo/image_thumb%5B2%5D.png" width="410" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Augmenting path&lt;/strong&gt;: a path from the source to the sink in the residual network, whose purpose is to increase the flow in the original one.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Ford-Fulkerson&lt;/strong&gt; method: start with no flow everywhere and increase the total flow in the network while there is an augmenting path from the source to the sink with no full forward edges or empty backward edges - a path in the residual network.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_52n3nML4Mbo/SQ_pLFJnHRI/AAAAAAAAB9Y/wJUUEi-m9XA/image%5B15%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="277" alt="image" src="http://lh3.ggpht.com/_52n3nML4Mbo/SQ_pLrwpGWI/AAAAAAAAB9c/Pd7Xg2fl0Xc/image_thumb%5B9%5D.png" width="767" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;A &lt;strong&gt;cut&lt;/strong&gt; in a flow network is simply a &lt;strong&gt;partition&lt;/strong&gt; of the vertices in two sets, let's call them A and B, in such a way that the &lt;strong&gt;source&lt;/strong&gt; vertex is in A and the &lt;strong&gt;sink&lt;/strong&gt; is in B.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;The&lt;/strong&gt; &lt;strong&gt;capacity of a cut&lt;/strong&gt; is the sum of the capacities of the edges that go from a vertex in A to a vertex in B. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;The flow of the cut&lt;/strong&gt; is the difference of the flows that go from A to B (the sum of the flows along the edges that have the starting point in A and the ending point in B), respectively from B to A, which is exactly the value of the flow in the network, due to the entering flow equals leaving flow - property, which is true for every vertex other than the source and the sink.&lt;/p&gt; &lt;p&gt;The flow of the cut is less or equal to the capacity of the cut due to the constraint of the flow being less or equal to the capacity of every edge.&lt;/p&gt; &lt;p&gt;This implies that &lt;strong&gt;the maximum flow is less or equal to every cut of the network&lt;/strong&gt;. This is where the max-flow min-cut theorem comes in and states that &lt;strong&gt;the value of the maximum flow through the network is exactly the value of the minimum cut of the network&lt;/strong&gt;.&lt;/p&gt; &lt;h3&gt;Maximum Bipartite Matching&lt;/h3&gt; &lt;p&gt;&lt;a title="http://shygypsy.com/tools/bpm.cpp" href="http://shygypsy.com/tools/bpm.cpp"&gt;http://shygypsy.com/tools/bpm.cpp&lt;/a&gt;&amp;nbsp;&amp;nbsp; (a bpm code)&lt;/p&gt; &lt;p&gt;UVa Problems: &lt;/p&gt; &lt;ul&gt; &lt;li&gt; 10080: Gopher (II)&amp;nbsp; (跟670几乎一样，先确定graph[][]即可,用scanf("%lf", ..) 和eps比较double型)&lt;/li&gt; &lt;li&gt; 10092: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;page=show_problem&amp;amp;category=12&amp;amp;problem=1033&amp;amp;mosmsg=Submission+received+with+ID+6777193"&gt;The Problem with the Problem Setter&lt;/a&gt;&amp;nbsp; (L: the number of problems that should be included; R: the total number of problems in the pool)&lt;/li&gt; &lt;li&gt; 259:&amp;nbsp;&amp;nbsp; &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;page=show_problem&amp;amp;category=4&amp;amp;problem=195&amp;amp;mosmsg=Submission+received+with+ID+6777104"&gt;Software Allocation&lt;/a&gt; (每台机子只能run一个application, 又是典型的0-1 assignment)&lt;/li&gt; &lt;li&gt;670:&amp;nbsp;&amp;nbsp; &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;category=8&amp;amp;page=show_problem&amp;amp;problem=611"&gt;The dog task&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;blockquote&gt; &lt;p&gt;其实就是先填一个graph[][]即可，在每两个master点之间，确定dog能到达哪些interesting places. 然后就是一个0-1 assignment问题而已。另注意double型比较用了eps = 1e-18(开始用1e-15 WA: )&lt;/p&gt; &lt;p&gt;special case: &lt;/p&gt; &lt;p&gt;2 1&lt;br&gt;0 0 2 2&lt;br&gt;3 3&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;#include &amp;lt;cmath&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;br /&gt;#define MAX 101&lt;br /&gt;#define eps 1e-18&lt;br /&gt;&lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; pair&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; ii;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; graph[MAX][MAX];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; seen[MAX];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; matchL[MAX], matchR[MAX];&lt;br /&gt;&lt;span style="color: #008000"&gt;// n: dim of L; m: dim of R&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n, m;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; bpm( &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; u ) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;( &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v = 0; v &amp;lt; m; v++ ) &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( graph[u][v] )&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( seen[v] ) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;        seen[v] = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( matchR[v] &amp;lt; 0 || bpm( matchR[v] ) )&lt;br /&gt;        {&lt;br /&gt;            matchL[u] = v;&lt;br /&gt;            matchR[v] = u;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;double&lt;/span&gt; dist(ii a, ii b) {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; sqrt((a.first - b.first) * (a.first - b.first) + &lt;br /&gt;              (a.second - b.second) * (a.second - b.second) + 0.0);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ndata;&lt;br /&gt;  scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;ndata);&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(ndata--) {&lt;br /&gt;    scanf("&lt;span style="color: #8b0000"&gt;%d %d &lt;/span&gt;", &amp;amp;n, &amp;amp;m);&lt;br /&gt;&lt;br /&gt;    vector&amp;lt;ii&amp;gt; master(n);&lt;br /&gt;    vector&amp;lt;ii&amp;gt; place(m);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i)&lt;br /&gt;      scanf("&lt;span style="color: #8b0000"&gt;%d %d &lt;/span&gt;", &amp;amp;master[i].first, &amp;amp;master[i].second);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m; ++i)&lt;br /&gt;      scanf("&lt;span style="color: #8b0000"&gt;%d %d &lt;/span&gt;", &amp;amp;place[i].first, &amp;amp;place[i].second);&lt;br /&gt;&lt;br /&gt;    memset(graph, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(graph));&lt;br /&gt;    memset( matchL, -1, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;( matchL ) );&lt;br /&gt;    memset( matchR, -1, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;( matchR ) );&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n-1; ++i) {&lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #008000"&gt;// master's walking distance doubled&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; d2 = dist(master[i], master[i+1]) * 2;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; m; ++j) {&lt;br /&gt;        &lt;span style="color: #008000"&gt;// dog's walking distance&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; dogdist = dist(master[i], place[j]) + dist(place[j], master[i+1]);&lt;br /&gt;        &lt;span style="color: #008000"&gt;// as long as dog's walking distance is no more than 2xmaster's, the dog can visit this place&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(d2 - dogdist&amp;gt;= eps) &lt;br /&gt;          graph[i][j] = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cnt = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;( &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++ i){&lt;br /&gt;      memset(seen, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;( seen ) );&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(bpm(i)) cnt++;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", n+cnt);&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;%d %d&lt;/span&gt;", master[0].first, master[0].second);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(i) printf("&lt;span style="color: #8b0000"&gt; %d %d&lt;/span&gt;", master[i].first, master[i].second);&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(matchL[i] != -1) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p = matchL[i];&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt; %d %d&lt;/span&gt;", place[p].first, place[p].second);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;");&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(ndata) printf("&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;");&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;663: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;category=8&amp;amp;page=show_problem&amp;amp;problem=604"&gt;Sorting Slides&lt;/a&gt;&amp;nbsp; (use point in rectangle to get graph[][])&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;这题难点在于要输出unique的matching, 我是run max bipartite matching 算法 |E|次(the number of edges), 每次检查uniqueness&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; Rect {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; xmin;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; xmax;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ymin;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ymax;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#define MAX 27 &lt;span style="color: #008000"&gt;// the number of alphabet&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; graph[MAX][MAX];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; seen[MAX];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; matchL[MAX], matchR[MAX];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n;&lt;br /&gt;Rect slides[MAX];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; exist;      &lt;span style="color: #008000"&gt;// if solution already exists&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; savedR[MAX]; &lt;span style="color: #008000"&gt;// save previous solution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// if a points is inside a rectangle&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; ptInRect(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y, Rect r) {&lt;br /&gt;  &lt;span style="color: #008000"&gt;//No number will lie on a slide boundary.&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (x &amp;gt; r.xmin &amp;amp;&amp;amp; x &amp;lt; r.xmax &amp;amp;&amp;amp; y &amp;gt; r.ymin &amp;amp;&amp;amp; y &amp;lt; r.ymax) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; bpm( &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; u ) {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;( &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v = 0; v &amp;lt; n; v++ ) &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( graph[u][v] )&lt;br /&gt;  {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( seen[v] ) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;    seen[v] = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( matchR[v] &amp;lt; 0 || bpm( matchR[v] ) )&lt;br /&gt;    {&lt;br /&gt;      matchL[u] = v;&lt;br /&gt;      matchR[v] = u;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ndata = 0;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;n) &amp;amp;&amp;amp; n) {&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;Heap %d\n&lt;/span&gt;", ++ndata);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;      scanf("&lt;span style="color: #8b0000"&gt;%d %d %d %d &lt;/span&gt;", &amp;amp;slides[i].xmin, &lt;br /&gt;                            &amp;amp;slides[i].xmax,&lt;br /&gt;                            &amp;amp;slides[i].ymin,&lt;br /&gt;                            &amp;amp;slides[i].ymax);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    memset(graph, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(graph));&lt;br /&gt;    memset(savedR, -1, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(savedR));&lt;br /&gt;    exist = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x, y;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;      scanf("&lt;span style="color: #8b0000"&gt;%d %d &lt;/span&gt;", &amp;amp;x, &amp;amp;y);&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; n; ++j)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(ptInRect(x, y, slides[j]))&lt;br /&gt;          graph[i][j] = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cnt = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; u = 0; u &amp;lt; n; ++u) {&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v = 0; v &amp;lt; n; ++v) {&lt;br /&gt;        &lt;span style="color: #008000"&gt;// each time, put one edge into the match&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;// and try to construct the max bipartite match based on that&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(!graph[u][v]) &lt;br /&gt;          &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        memset( matchL, -1, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;( matchL ) );&lt;br /&gt;        memset( matchR, -1, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;( matchR ) );&lt;br /&gt;        &lt;br /&gt;        matchL[u] = v;&lt;br /&gt;        matchR[v] = u;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cnt = 1;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;( &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++ i){&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (i == u) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;          memset(seen, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;( seen ));&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(bpm(i)) cnt++;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(exist) {&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = 0; k &amp;lt; n; ++k)&lt;br /&gt;            &lt;span style="color: #008000"&gt;//check uniqueness&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (matchR[k] != savedR[k])&lt;br /&gt;              savedR[k] = -1;  &lt;span style="color: #008000"&gt;// not unique, reset to -1 &lt;/span&gt;&lt;br /&gt;        } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {&lt;br /&gt;          memcpy(savedR, matchR, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)*n); &lt;span style="color: #008000"&gt;// save the first solution&lt;/span&gt;&lt;br /&gt;          exist = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cardinal = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(savedR[i] != -1) {&lt;br /&gt;        ++cardinal;&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt;(%c,%d)&lt;/span&gt;", i + 'A', savedR[i] + 1);&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(++i; i &amp;lt; n; ++i) {&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(savedR[i] != -1) {&lt;br /&gt;        ++cardinal;&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt; (%c,%d)&lt;/span&gt;", i + 'A', savedR[i] + 1);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(cardinal == 0) &lt;br /&gt;      printf("&lt;span style="color: #8b0000"&gt;none&lt;/span&gt;");&lt;br /&gt;&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;\n\n&lt;/span&gt;");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1035728633202707148?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1035728633202707148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1035728633202707148'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/maximun-flow.html' title='Maximun Flow'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_52n3nML4Mbo/SQ_pHqwCNpI/AAAAAAAAB9I/-0Fjmr00WCg/s72-c/image_thumb%5B4%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-3281189889074564808</id><published>2008-11-03T21:04:00.001-08:00</published><updated>2008-11-03T21:21:01.104-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><title type='text'>Hungarian Method</title><content type='html'>&lt;p&gt;Easy to understand examples:&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm" href="http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm"&gt;http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.ams.jhu.edu/~castello/362/Handouts/hungarian.pdf" href="http://www.ams.jhu.edu/~castello/362/Handouts/hungarian.pdf"&gt;http://www.ams.jhu.edu/~castello/362/Handouts/hungarian.pdf&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.public.iastate.edu/~ddoty/HungarianAlgorithm.html" href="http://www.public.iastate.edu/~ddoty/HungarianAlgorithm.html"&gt;http://www.public.iastate.edu/~ddoty/HungarianAlgorithm.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;animation: &lt;a title="http://www.ifors.ms.unimelb.edu.au/tutorial/hungarian/index.html" href="http://www.ifors.ms.unimelb.edu.au/tutorial/hungarian/index.html"&gt;http://www.ifors.ms.unimelb.edu.au/tutorial/hungarian/index.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;topcoder tutorial: &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=hungarianAlgorithm"&gt;Assignment Problem and Hungarian Algorithm&lt;/a&gt; (very good regarding theory and c++ code)&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.math.uwo.ca/~mdawes/courses/344/kuhn-munkres.pdf" href="http://www.math.uwo.ca/~mdawes/courses/344/kuhn-munkres.pdf"&gt;http://www.math.uwo.ca/~mdawes/courses/344/kuhn-munkres.pdf&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-3281189889074564808?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3281189889074564808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3281189889074564808'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/hungarian-method.html' title='Hungarian Method'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2474671298439341212</id><published>2008-11-02T15:31:00.001-08:00</published><updated>2008-11-02T22:05:03.052-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='string'/><title type='text'>String Searching</title><content type='html'>&lt;p&gt;&lt;a title="http://allisons.org/ll/AlgDS/Strings/" href="http://allisons.org/ll/AlgDS/Strings/"&gt;http://allisons.org/ll/AlgDS/Strings/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/String_searching_algorithm" href="http://en.wikipedia.org/wiki/String_searching_algorithm"&gt;http://en.wikipedia.org/wiki/String_searching_algorithm&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm" href="http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm"&gt;http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2474671298439341212?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2474671298439341212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2474671298439341212'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/string-searching.html' title='String Searching'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2052843116757821921</id><published>2008-11-02T13:32:00.001-08:00</published><updated>2008-11-02T13:32:05.409-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='string'/><title type='text'>Suffix Tree</title><content type='html'>&lt;p&gt;&lt;a href="http://www.cs.mcgill.ca/~cs251/OldCourses/1997/topic7/#NON%20COMPACT"&gt;Tries and suffix tree&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Suffix_tree#cite_note-Gus97-4"&gt;wiki - Suffix Trees&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="http://allisons.org/ll/AlgDS/Tree/Suffix/" href="http://allisons.org/ll/AlgDS/Tree/Suffix/"&gt;http://allisons.org/ll/AlgDS/Tree/Suffix/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_52n3nML4Mbo/SQ4cNeEW3WI/AAAAAAAAB80/IMHBFI_H6_4/image%5B3%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://lh5.ggpht.com/_52n3nML4Mbo/SQ4cQKAa3-I/AAAAAAAAB84/lDNoENnb5Ko/image_thumb%5B1%5D.png" width="427" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_52n3nML4Mbo/SQ4cTc2fGPI/AAAAAAAAB88/Tc5QXcgXmpo/image%5B12%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="253" alt="image" src="http://lh6.ggpht.com/_52n3nML4Mbo/SQ4cUk7FUGI/AAAAAAAAB9A/dGki2GLSBuk/image_thumb%5B8%5D.png" width="424" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The suffix tree can be built in O(n) time (linear time regarding the length of strings) due to Ukkonen (1995).&lt;/p&gt; &lt;p&gt;Applications: [1,2,3] from &lt;a title="http://allisons.org/ll/AlgDS/Tree/Suffix/" href="http://allisons.org/ll/AlgDS/Tree/Suffix/"&gt;http://allisons.org/ll/AlgDS/Tree/Suffix/&lt;/a&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;String Search: Searching for a substring, &lt;code&gt;pat[1..m]&lt;/code&gt;, in &lt;code&gt;txt[1..n]&lt;/code&gt;, can be solved in O(m) time (after the suffix tree for &lt;code&gt;txt&lt;/code&gt; has been built in O(n) time). &lt;/li&gt; &lt;li&gt;Palindromes: The longest palindrome of &lt;code&gt;txt[1..n]&lt;/code&gt; can be found in O(n) time, e.g. by building the suffix tree for &lt;code&gt;txt$reverse(txt)#&lt;/code&gt; or by building the generalized suffix tree for &lt;code&gt;txt&lt;/code&gt; and &lt;code&gt;reverse(txt)&lt;/code&gt;.&lt;/li&gt; &lt;li&gt;Longest Common String:&amp;nbsp; The &lt;em&gt;longest common substring&lt;/em&gt; of two strings, &lt;code&gt;txt&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; and &lt;code&gt;txt&lt;sub&gt;2&lt;/sub&gt;&lt;/code&gt;, can be found by building a &lt;em&gt;generalized&lt;/em&gt; suffix tree for &lt;code&gt;txt&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; and &lt;code&gt;txt&lt;sub&gt;2&lt;/sub&gt;&lt;/code&gt;: Each node is &lt;em&gt;marked&lt;/em&gt; to indicate if it represents a suffix of &lt;code&gt;txt&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; or &lt;code&gt;txt&lt;sub&gt;2&lt;/sub&gt;&lt;/code&gt; or both. The deepest node marked for both &lt;code&gt;txt&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; and &lt;code&gt;txt&lt;sub&gt;2&lt;/sub&gt;&lt;/code&gt; represents the longest common substring.&amp;nbsp; Equivalently, one can build a (basic) suffix tree for the string &lt;code&gt;txt&lt;sub&gt;1&lt;/sub&gt;$txt&lt;sub&gt;2&lt;/sub&gt;#&lt;/code&gt;, where `$' is a special terminator for &lt;code&gt;txt&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; and `#' is a special terminator for &lt;code&gt;txt&lt;sub&gt;2&lt;/sub&gt;&lt;/code&gt;. The longest common substring is indicated by the deepest fork node that has both `...$...' and `...#...' (no $) beneath it.&lt;/li&gt;&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2052843116757821921?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2052843116757821921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2052843116757821921'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/11/suffix-tree.html' title='Suffix Tree'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_52n3nML4Mbo/SQ4cQKAa3-I/AAAAAAAAB84/lDNoENnb5Ko/s72-c/image_thumb%5B1%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-807491424754270240</id><published>2008-10-24T12:27:00.001-07:00</published><updated>2008-10-24T16:11:34.895-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>google c++ coding style</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a title="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Header_File_Dependencies#Header_File_Dependencies" href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Header_File_Dependencies#Header_File_Dependencies"&gt;http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Header_File_Dependencies#Header_File_Dependencies&lt;/a&gt;&lt;/p&gt; &lt;h5&gt;&lt;a name="Header_File_Dependencies"&gt;Header File Dependencies&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;How can we use a class &lt;code&gt;Foo&lt;/code&gt; in a header file without access to its definition?  &lt;ul&gt; &lt;li&gt;We can declare data members of type &lt;code&gt;Foo*&lt;/code&gt; or &lt;code&gt;Foo&amp;amp;&lt;/code&gt;.  &lt;li&gt;We can declare (but not define) functions with arguments, and/or return values, of type &lt;code&gt;Foo&lt;/code&gt;.  &lt;li&gt;We can declare static data members of type &lt;code&gt;Foo&lt;/code&gt;. This is because static data members are defined outside the class definition. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;On the other hand, you must include the header file for &lt;code&gt;Foo&lt;/code&gt; if your class subclasses &lt;code&gt;Foo&lt;/code&gt; or has a data member of type &lt;code&gt;Foo&lt;/code&gt;.  &lt;h5&gt;&lt;a name="Inline_Functions"&gt;Inline Functions&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;A decent rule of thumb is to not inline a function if it is more than 10 lines long. Beware of destructors, which are often longer than they appear because of implicit member- and base-destructor calls!  &lt;p&gt;Another useful rule of thumb: it's typically not cost effective to inline functions with loops or switch statements (unless, in the common case, the loop or switch statement is never executed).  &lt;h5&gt;&lt;a name="Function_Parameter_Ordering"&gt;Function Parameter Ordering&lt;/a&gt;&lt;/h5&gt; &lt;p&gt; When defining a function, parameter order is: inputs, then output&lt;/p&gt; &lt;p&gt;Parameters to C/C++ functions are either input to the function, output from the function, or both. Input parameters are usually values or &lt;code&gt;const&lt;/code&gt; references, while output and input/output parameters will be non-&lt;code&gt;const&lt;/code&gt; pointers. When ordering function parameters, put all input-only parameters before any output parameters. In particular, do not add new parameters to the end of the function just because they are new; place new input-only parameters before the output parameters. &lt;/p&gt; &lt;h5&gt;&lt;a name="Local_Variables"&gt;Local Variables&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;There is one caveat: if the variable is an object, its constructor is invoked every time it enters scope and is created, and its destructor is invoked every time it goes out of scope. &lt;pre&gt;// Inefficient implementation:&lt;br /&gt;for (int i = 0; i &amp;lt; 1000000; ++i) {&lt;br /&gt;  Foo f;  // My ctor and dtor get called 1000000 times each.&lt;br /&gt;  f.DoSomething(i);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;It may be more efficient to declare such a variable used in a loop outside that loop: &lt;pre&gt;Foo f;  // My ctor and dtor get called once each.&lt;br /&gt;for (int i = 0; i &amp;lt; 1000000; ++i) {&lt;br /&gt;  f.DoSomething(i);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;h5&gt;&lt;a name="Doing_Work_in_Constructors"&gt;Doing Work in Constructors&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Do only trivial initialization in a constructor. If at all possible, use an &lt;code&gt;Init()&lt;/code&gt; method for non-trivial initialization. &lt;br /&gt;&lt;p&gt;Decision: If your object requires non-trivial initialization, consider having an explicit &lt;code&gt;Init()&lt;/code&gt; method and/or adding a member flag that indicates whether the object was successfully initialized. &lt;br /&gt;&lt;h5&gt;&lt;a name="Explicit_Constructors"&gt;Explicit Constructors&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Use the C++ keyword &lt;code&gt;explicit&lt;/code&gt; for constructors with one argument. &lt;br /&gt;&lt;p&gt;Definition: Normally, if a constructor takes one argument, it can be used as a conversion. For instance, if you define &lt;code&gt;Foo::Foo(string name)&lt;/code&gt; and then pass a string to a function that expects a &lt;code&gt;Foo&lt;/code&gt;, the constructor will be called to convert the string into a &lt;code&gt;Foo&lt;/code&gt; and will pass the &lt;code&gt;Foo&lt;/code&gt; to your function for you. This can be convenient but is also a source of trouble when things get converted and new objects created without you meaning them to. Declaring a constructor &lt;code&gt;explicit&lt;/code&gt; prevents it from being invoked implicitly as a conversion. &lt;br /&gt;&lt;p&gt;Pros: Avoids undesirable conversions. &lt;br /&gt;&lt;p&gt;Cons: None. &lt;br /&gt;&lt;p&gt;Decision: &lt;br /&gt;&lt;p&gt;We require all single argument constructors to be explicit. Always put &lt;code&gt;explicit&lt;/code&gt; in front of one-argument constructors in the class definition: &lt;code&gt;explicit Foo(string name);&lt;/code&gt;&lt;br /&gt;&lt;p&gt;The exception is copy constructors, which, in the rare cases when we allow them, should probably not be &lt;code&gt;explicit&lt;/code&gt;. Classes that are intended to be transparent wrappers around other classes are also exceptions. Such exceptions should be clearly marked with comments. &lt;br /&gt;&lt;h5&gt;&lt;a name="Copy_Constructors"&gt;Copy Constructors&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Consider adding dummy declarations for the copy constructor and assignment operator in the class' &lt;code&gt;private:&lt;/code&gt; section, without providing definitions. With these dummy routines marked private, a compilation error will be raised if other code attempts to use them. For convenience, a &lt;code&gt;DISALLOW_COPY_AND_ASSIGN&lt;/code&gt; macro can be used: &lt;pre&gt;&lt;span style="color: #008000"&gt;// A macro to disallow the copy constructor and operator= functions&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// This should be used in the private: declarations for a class&lt;/span&gt;&lt;br /&gt;#define DISALLOW_COPY_AND_ASSIGN(TypeName) \&lt;br /&gt;  TypeName(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; TypeName&amp;amp;);               \&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt;=(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; TypeName&amp;amp;)Then, in &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Foo: &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Foo {&lt;br /&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;  Foo(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; f);&lt;br /&gt;  ~Foo();&lt;br /&gt;&lt;br /&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt;:&lt;br /&gt;  DISALLOW_COPY_AND_ASSIGN(Foo);&lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;&lt;h5&gt;&lt;a name="Structs_vs._Classes"&gt;Structs vs. Classes&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Use a &lt;code&gt;struct&lt;/code&gt; only for passive objects that carry data; everything else is a &lt;code&gt;class&lt;/code&gt;. &lt;br /&gt;&lt;h5&gt;&lt;a name="Declaration_Order"&gt;Declaration Order&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Your class definition should start with its &lt;code&gt;public:&lt;/code&gt; section, followed by its &lt;code&gt;protected:&lt;/code&gt; section and then its &lt;code&gt;private:&lt;/code&gt; section. If any of these sections are empty, omit them. &lt;br /&gt;&lt;p&gt;Within each section, the declarations generally should be in the following order: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Typedefs and Enums &lt;br /&gt;&lt;li&gt;Constants &lt;br /&gt;&lt;li&gt;Constructors &lt;br /&gt;&lt;li&gt;Destructor &lt;br /&gt;&lt;li&gt;Methods, including static methods &lt;br /&gt;&lt;li&gt;Data Members, including static data members &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;The &lt;code&gt;DISALLOW_COPY_AND_ASSIGN&lt;/code&gt; macro invocation should be at the end of the &lt;code&gt;private:&lt;/code&gt; section. It should be the last thing in the class. &lt;/p&gt;&lt;br /&gt;&lt;h5&gt;&lt;a name="Reference_Arguments"&gt;Reference Arguments&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;All parameters passed by reference must be labeled &lt;code&gt;const&lt;/code&gt;. &lt;br /&gt;&lt;p&gt;Within function parameter lists all references must be &lt;code&gt;const&lt;/code&gt;: &lt;pre&gt;void Foo(const string &amp;amp;in, string *out);&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;In fact it is a very strong convention that input arguments are values or &lt;code&gt;const&lt;/code&gt; references while output arguments are pointers. Input parameters may be &lt;code&gt;const&lt;/code&gt; pointers, but we never allow non-&lt;code&gt;const&lt;/code&gt; reference parameters. &lt;br /&gt;&lt;h5&gt;&lt;a name="Casting"&gt;Casting&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Use C++ casts like &lt;code&gt;static_cast&amp;lt;&amp;gt;()&lt;/code&gt;. Do not use other cast formats like &lt;code&gt;int y = (int)x;&lt;/code&gt; or &lt;code&gt;int y = int(x);&lt;/code&gt;. &lt;br /&gt;&lt;p&gt;Do not use C-style casts. Instead, use these C++-style casts. &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Use &lt;code&gt;static_cast&lt;/code&gt; as the equivalent of a C-style cast that does value conversion, or when you need to explicitly up-cast a pointer from a class to its superclass. &lt;br /&gt;&lt;li&gt;Use &lt;code&gt;const_cast&lt;/code&gt; to remove the &lt;code&gt;const&lt;/code&gt; qualifier (see &lt;a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Header_File_Dependencies#Use_of_const"&gt;const&lt;/a&gt;). &lt;br /&gt;&lt;li&gt;Use &lt;code&gt;reinterpret_cast&lt;/code&gt; to do unsafe conversions of pointer types to and from integer and other pointer types. Use this only if you know what you are doing and you understand the aliasing issues. &lt;br /&gt;&lt;li&gt;Do not use &lt;code&gt;dynamic_cast&lt;/code&gt; except in test code. If you need to know type information at runtime in this way outside of a unittest, you probably have a &lt;a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Header_File_Dependencies#Run-Time_Type_Information__RTTI_"&gt;design flaw&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h5&gt;&lt;a name="sizeof"&gt;sizeof&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Use &lt;code&gt;sizeof(&lt;var&gt;varname&lt;/var&gt;)&lt;/code&gt; instead of &lt;code&gt;sizeof(&lt;var&gt;type&lt;/var&gt;)&lt;/code&gt; whenever possible. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Use &lt;code&gt;sizeof(&lt;var&gt;varname&lt;/var&gt;)&lt;/code&gt; because it will update appropriately if the type of the variable changes. &lt;code&gt;sizeof(&lt;var&gt;type&lt;/var&gt;)&lt;/code&gt; may make sense in some cases, but should generally be avoided because it can fall out of sync if the variable's type changes. &lt;pre&gt;Struct data;&lt;br /&gt;memset(&amp;amp;data, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(data));&lt;/pre&gt;&lt;pre&gt;memset(&amp;amp;data, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(Struct));&lt;/pre&gt;&lt;br /&gt;&lt;h5&gt;&lt;a name="File_Comments"&gt;File Comments&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Every file should contain the following items, in order: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;a copyright statement (for example, &lt;code&gt;Copyright 2008 Google Inc.&lt;/code&gt;) &lt;br /&gt;&lt;li&gt;a license boilerplate. Choose the appropriate boilerplate for the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL) &lt;br /&gt;&lt;li&gt;an author line to identify the original author of the file &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;File Contents&lt;br /&gt;&lt;p&gt;Every file should have a comment at the top, below the and author line, that describes the contents of the file. &lt;br /&gt;&lt;p&gt;Generally a &lt;code&gt;.h&lt;/code&gt; file will describe the classes that are declared in the file with an overview of what they are for and how they are used. A &lt;code&gt;.cc&lt;/code&gt; file should contain more information about implementation details or discussions of tricky algorithms. If you feel the implementation details or a discussion of the algorithms would be useful for someone reading the &lt;code&gt;.h&lt;/code&gt;, feel free to put it there instead, but mention in the &lt;code&gt;.cc&lt;/code&gt; that the documentation is in the &lt;code&gt;.h&lt;/code&gt; file. &lt;br /&gt;&lt;p&gt;Do not duplicate comments in both the &lt;code&gt;.h&lt;/code&gt; and the &lt;code&gt;.cc&lt;/code&gt;. Duplicated comments diverge. &lt;br /&gt;&lt;p&gt;Every class definition should have an accompanying comment that describes what it is for and how it should be used. &lt;pre&gt;&lt;span style="color: #008000"&gt;// Iterates over the contents of a GargantuanTable.  Sample usage:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//    GargantuanTable_Iterator* iter = table-&amp;gt;NewIterator();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//    for (iter-&amp;gt;Seek("foo"); !iter-&amp;gt;done(); iter-&amp;gt;Next()) {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//      process(iter-&amp;gt;key(), iter-&amp;gt;value());&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//    }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//    delete iter;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; GargantuanTable_Iterator {&lt;br /&gt;  ...&lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;&lt;h5&gt;&lt;a name="Function_Comments"&gt;Function Comments&lt;/a&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Declaration comments describe use of the function; comments at the definition of a function describe operation. &lt;br /&gt;&lt;p&gt;Function Declarations&lt;br /&gt;&lt;p&gt;Every function declaration should have comments immediately preceding it that describe what the function does and how to use it. These comments should be descriptive ("Opens the file") rather than imperative ("Open the file"); the comment describes the function, it does not tell the function what to do. In general, these comments do not describe how the function performs its task. Instead, that should be left to comments in the function definition. &lt;br /&gt;&lt;p&gt;Types of things to mention in comments at the function declaration: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;What the inputs and outputs are. &lt;br /&gt;&lt;li&gt;For class member functions: whether the object remembers reference arguments beyond the duration of the method call, and whether it will free them or not. &lt;br /&gt;&lt;li&gt;If the function allocates memory that the caller must free. &lt;br /&gt;&lt;li&gt;Whether any of the arguments can be &lt;code&gt;NULL&lt;/code&gt;. &lt;br /&gt;&lt;li&gt;If there are any performance implications of how a function is used. &lt;br /&gt;&lt;li&gt;If the function is re-entrant. What are its synchronization assumptions? &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Here is an example: &lt;pre&gt;&lt;span style="color: #008000"&gt;// Returns an iterator for this table.  It is the client's&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// responsibility to delete the iterator when it is done with it,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// and it must not use the iterator once the GargantuanTable object&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// on which the iterator was created has been deleted.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// The iterator is initially positioned at the beginning of the table.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// This method is equivalent to:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//    Iterator* iter = table-&amp;gt;NewIterator();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//    iter-&amp;gt;Seek("");&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//    return iter;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// If you are going to immediately seek to another place in the&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// returned iterator, it will be faster to use NewIterator()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// and avoid the extra seek.&lt;/span&gt;&lt;br /&gt;Iterator* GetIterator() &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-807491424754270240?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/807491424754270240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/807491424754270240'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/google-c-coding-style.html' title='google c++ coding style'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-7570169209203982447</id><published>2008-10-23T18:35:00.001-07:00</published><updated>2008-10-23T18:35:56.395-07:00</updated><title type='text'>random programs</title><content type='html'>&lt;p&gt;摘几个programming pearls 上提到的random function.&lt;/p&gt; &lt;p&gt;1. knuth version. 从1-n之间生成有序的m个不同的随机数( the output is a sorted list of m random integers in the range 0...n-1 in which no integer occurs more than once).&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; genknuth(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n) {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;    &lt;span style="color: #008000"&gt;/* select m of remaining n-i */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((bigrand() % (n-i)) &amp;lt; m) {&lt;br /&gt;      cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;";&lt;br /&gt;      --m;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;2. shuffle the first m elements of the array. output the sorted list of the m random numbers.&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; genshuf(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n) {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i, j;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; *x = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;[n];&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; n; ++i)&lt;br /&gt;    x[i] = i;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;    j = randint(i, n-1);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; t = x[i]; x[i] = x[j]; x[j] = t;&lt;br /&gt;  }&lt;br /&gt;  sort(x, x+m);&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; m; ++i)&lt;br /&gt;    cout &amp;lt;&amp;lt; x[i] &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;3. floyd. This algorithm uses only m random numbers, even in the worst case.&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; genfloyd(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n) {&lt;br /&gt;  set&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; S;&lt;br /&gt;  set&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;::iterator i;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = n-m; j &amp;lt; n; ++j) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; t = bigrand() % (j+1);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(S.find(t) == S.end())&lt;br /&gt;      S.insert(t); &lt;span style="color: #008000"&gt;// t not in S&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;      S.insert(j); &lt;span style="color: #008000"&gt;// t in S&lt;/span&gt;&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = S.begin(); i != S.end(); ++i)&lt;br /&gt;    cout &amp;lt;&amp;lt; *i &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;";&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;4. reservoir sampling. when we do not know the length of the data ( we see the data sequentially. )&lt;/p&gt;&lt;br /&gt;&lt;p&gt;We always select the first line, we select the second line with probability one half, the third line with probability one third, and so on. At the end of the process, each line has the same probability of being chosen (1/n, where n is the total number of lines in the article).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-7570169209203982447?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/7570169209203982447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/7570169209203982447'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/random-programs.html' title='random programs'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-587152289038373112</id><published>2008-10-19T20:30:00.001-07:00</published><updated>2008-10-19T22:09:10.855-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><title type='text'>counting sort + bit operation</title><content type='html'>&lt;p&gt;UVa problem: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;page=show_problem&amp;amp;problem=496"&gt;Bridge Hands&lt;/a&gt;&lt;/p&gt; &lt;p&gt;每一花色牌不超过13张，4种花色，用一个long long表示，每16位一组表示一个花色&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.h&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; player[4];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p[90];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; ip[4] = {'C', 'D', 'S', 'H'};&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; seat[90];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; iseat[4] = {'S','W','N','E'};&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; idx[90];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; inverse_idx[15] = {'0','1','2','3','4','5','6','7','8','9','T','J','Q','K','A'};&lt;br /&gt;&lt;span style="color: #008000"&gt;//int __builtin_ctz(long long);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; buff[60];&lt;br /&gt;    seat['S'] = p['C'] = 0; &lt;br /&gt;    seat['W'] = p['D'] = 1;&lt;br /&gt;    seat['N'] = p['S'] = 2;&lt;br /&gt;    seat['E'] = p['H'] = 3;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i, j;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = 2; i &amp;lt;= 9; ++i)&lt;br /&gt;        idx[i+48] = i;&lt;br /&gt;    idx['T'] = 10;&lt;br /&gt;    idx['J'] = 11;&lt;br /&gt;    idx['Q'] = 12;&lt;br /&gt;    idx['K'] = 13;&lt;br /&gt;    idx['A'] = 14;       &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; t;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;((t = getchar()) != '#') {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(gets(buff) &amp;amp;&amp;amp; strlen(buff)==0){};&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; side = seat[t];&lt;br /&gt;        memset(player, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(player));&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; 52; i += 2) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(++side == 4) side = 0;&lt;br /&gt;            &lt;span style="color: #008000"&gt;/* get card, set its bit */&lt;/span&gt;&lt;br /&gt;            player[side] |= 1LL&amp;lt;&amp;lt; (p[buff[i]]&amp;lt;&amp;lt;4LL) + idx[buff[i+1]]; &lt;br /&gt;        }&lt;br /&gt;        gets(buff);&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; 52; i += 2) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(++side == 4) side = 0;&lt;br /&gt;            player[side] |= 1LL&amp;lt;&amp;lt; (p[buff[i]]&amp;lt;&amp;lt;4LL) + idx[buff[i+1]];&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; printed = 0;&lt;br /&gt;            printf("&lt;span style="color: #8b0000"&gt;%c: &lt;/span&gt;", iseat[i]); &lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(j = 0; j &amp;lt; 4; ++j) {                &lt;br /&gt;                &lt;span style="color: #008000"&gt;/* get current color */&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; c = player[i] &amp;amp; 0xffff;&lt;br /&gt;                player[i] &amp;gt;&amp;gt;= 16; &lt;span style="color: #008000"&gt;/* next color */&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(c) {&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pos = __builtin_ctz(c);&lt;br /&gt;                    c ^= 1LL &amp;lt;&amp;lt; pos;  &lt;span style="color: #008000"&gt;/* clear printed bit */&lt;/span&gt;&lt;br /&gt;                    printf("&lt;span style="color: #8b0000"&gt;%c%c&lt;/span&gt;", ip[j], inverse_idx[pos]); &lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(++printed &amp;lt; 13) printf("&lt;span style="color: #8b0000"&gt; &lt;/span&gt;");&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            printf("&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;/* gcc has built in __builtin_ctz, vc not*/ &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;/*&lt;br /&gt;int __builtin_ctz(long long c) {&lt;br /&gt;&lt;br /&gt;    for(int i = 0; i &amp;lt; 64; ++i)&lt;br /&gt;        if(c &amp;amp; (1LL&amp;lt;&amp;lt;i)) return i;&lt;br /&gt;}*/&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-587152289038373112?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/587152289038373112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/587152289038373112'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/couting-sort-bit-operation.html' title='counting sort + bit operation'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-6129279113700941760</id><published>2008-10-19T15:41:00.001-07:00</published><updated>2008-10-19T15:48:17.043-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>Maximum interval sum</title><content type='html'>&lt;p&gt;Or maximum contiguous subvector of the input.&lt;/p&gt; &lt;p&gt;Do a linear sweep from left to right, accumulate the sum. Start new interval whenever you encounter partial sum &amp;lt; 0.&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;/* 1-d linear alg O(n) */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; mis1d(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; line[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; size) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; maxv = -INF;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; size; ++i) {&lt;br /&gt;        p += line[i];&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p &amp;lt; 0) p = 0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p &amp;gt; maxv) maxv = p;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; maxv;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;In a 2D problem, we are expected to find a maximum sum subrectangle in a mxn matrix. &lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;We first calculate the accumulative sum in the dimension of length m (smaller dim). &lt;/li&gt;&lt;br /&gt;&lt;li&gt;We then use the above technique in the dimension of length n.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The total running time is O(m^2 n). (for nxn matrix, that is O(n^3) )&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;UVa problem: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;page=show_problem&amp;amp;problem=44"&gt;108&lt;/a&gt;, &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;page=show_problem&amp;amp;problem=777"&gt;836&lt;/a&gt;&lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;br /&gt;#define INF 999999999&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; M[101][101];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; partialSum[101][101];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; line[101];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;/* 1-d linear alg O(n) */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; mis1d(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; line[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; size) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; maxv = -INF;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; size; ++i) {&lt;br /&gt;        p += line[i];&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p &amp;lt; 0) p = 0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p &amp;gt; maxv) maxv = p;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; maxv;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;/* 2-D O(n^3) */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; mis2d(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; size) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; maxv = -INF;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; size; ++j) {&lt;br /&gt;        partialSum[0][j] = M[0][j];&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 1; i &amp;lt; size; i++)&lt;br /&gt;            partialSum[i][j] = partialSum[i-1][j] + M[i][j];&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; size; ++i) {   &lt;span style="color: #008000"&gt;// use from the i-th row&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = i; j &amp;lt; size; ++j) {  &lt;span style="color: #008000"&gt;// to the j-th row&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(i == j) &lt;br /&gt;                memcpy(line, M[i], size*&lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;));&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {&lt;br /&gt;                &lt;span style="color: #008000"&gt;// generate the data i to j-th row&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = 0; k &amp;lt; size; ++k)&lt;br /&gt;                    line[k] = partialSum[j][k] - partialSum[i][k];&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v = mis1d(line, size);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(v &amp;gt; maxv) maxv = v;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; maxv;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;n) == 1) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i)&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; n; ++j)&lt;br /&gt;                scanf("&lt;span style="color: #8b0000"&gt;%d&lt;/span&gt;", &amp;amp;M[i][j]);&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", mis2d(n));&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;Related problems:&lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;find the subvector with the sum closest to zeros&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;calc the accumulative sum so that cum[i] = x[0] + ... + x[i]&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The subvector x[l ... u] sums to zeros if cum[l-1] = cum[u]&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the subvector with the sum closest to zeros is found by locating the two closest elements in cum&lt;/li&gt;&lt;br /&gt;&lt;li&gt;which can be done in O(nlogn) by sorting&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;find the subvector with the sum closest to a given real number t.&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;a simple extension from the above case&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The subvector x[l ... u] sums to t if cum[l-1] + t = cum[u] and l-1&amp;lt;u&lt;/li&gt;&lt;br /&gt;&lt;li&gt;first nlogn sorting&lt;/li&gt;&lt;br /&gt;&lt;li&gt;then for each element, do a (log n) binary search for closest to (cum[i]+t)&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-6129279113700941760?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/6129279113700941760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/6129279113700941760'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/maximum-interval-sum.html' title='Maximum interval sum'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-8073706158260972785</id><published>2008-10-19T11:58:00.001-07:00</published><updated>2008-10-19T13:05:00.367-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>initialize upon the first use</title><content type='html'>&lt;p&gt;This is a technique coverd in Programming Pearls.&amp;nbsp; (Chap 1, Problems 9)&lt;/p&gt; &lt;p&gt;This method use constant time for initialization and for each vector access, and use extra space proportional to the size of the vector. Because this method reduces initialization time by using even more space, it should be considered only when space is cheap, time is deer and the vector is sparse.&lt;/p&gt; &lt;p&gt;My test code here ( #define COL&amp;nbsp;&amp;nbsp; to enable 2-D matrix test case)&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;ctime&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// max row and col size&lt;/span&gt;&lt;br /&gt;#define ROW 8000&lt;br /&gt;&lt;span style="color: #008000"&gt;// if 1-d, just comment the next line&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;#define COL 8000&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; top = 0;&lt;br /&gt;&lt;br /&gt;#ifndef COL&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; data[ROW];&lt;br /&gt;#define MAXE ROW&lt;br /&gt;#&lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; data[ROW][COL];&lt;br /&gt;#define MAXE ROW*COL&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// two additional array to implement a simple signature&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; from[MAXE];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; to[MAXE];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// if element i in the array is initialised &lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline bool&lt;/span&gt; exist(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j=0) {&lt;br /&gt;#ifdef COL&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; idx = COL*i+j;&lt;br /&gt;#&lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; idx = i;&lt;br /&gt;#endif&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(from[idx] &amp;lt; top &amp;amp;&amp;amp; to[from[idx]] == idx)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// assign data value to the i-th element&lt;/span&gt;&lt;br /&gt;#ifndef COL&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; setdata(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(!exist(i)) {        &lt;br /&gt;        from[i] = top;&lt;br /&gt;        to[top] = i;&lt;br /&gt;        ++ top;&lt;br /&gt;    }&lt;br /&gt;    data[i] = v;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#&lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; setdata(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(!exist(i, j)) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; idx = COL*i+j;&lt;br /&gt;        from[idx] = top;&lt;br /&gt;        to[top] = idx;&lt;br /&gt;        ++ top;&lt;br /&gt;    }&lt;br /&gt;    data[i][j] = v;&lt;br /&gt;}&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; argc, &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;* argv[]) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; startt = clock();&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;initialize at start time--\n&lt;/span&gt;");&lt;br /&gt;    memset(data, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(data));&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(argc &amp;lt; 2 || atoi(argv[1]) &amp;gt; ROW) n = 100;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; n = atoi(argv[1]);&lt;br /&gt;&lt;br /&gt;#ifndef COL&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i)&lt;br /&gt;        data[i] = (i*i-i)/(i+1);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; starts = clock();&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;use %d\n&lt;/span&gt;", starts-startt);&lt;br /&gt;&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;no initialization--\n&lt;/span&gt;");&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++)&lt;br /&gt;        setdata(i, (i*i-i)/(i+1));&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;use %d\n&lt;/span&gt;", clock()-starts); &lt;br /&gt;&lt;br /&gt;#&lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; n; ++j)&lt;br /&gt;            data[i][j] = (i*j-i)/(i+1);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; starts = clock();&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;use %d\n&lt;/span&gt;", starts-startt);&lt;br /&gt;&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;no initialization--\n&lt;/span&gt;");&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; n; ++j)&lt;br /&gt;            setdata(i, j, (i*j-i)/(i+1));&lt;br /&gt;&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;use %d\n&lt;/span&gt;", clock()-starts);&lt;br /&gt;#endif&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;From the test result: &lt;/pre&gt;&lt;br /&gt;&lt;li&gt;When the operations overhead is much less than the initialization cost, use init upon the first use. &lt;br /&gt;&lt;li&gt;When the vector/matrix is not sparse (e.g., &amp;gt; 10% full), memset is fast enough. &lt;br /&gt;&lt;li&gt;It seems the access speed of alg2 is 10 times slower than direct access speed &lt;pre&gt;+------------+----------+-----------+----------+&lt;br /&gt;|matrix dim  |#  op     |alg 1 (ms) |alg 2 (ms)| &lt;br /&gt;|8000 x 8000 |10 x 10   |312        |0         |&lt;br /&gt;|8000 x 8000 |100x100   |312        |0         |&lt;br /&gt;|8000 x 8000 |1000x1000 |328        |187       |&lt;br /&gt;|8000 x 8000 |4000x4000 |531        |2922      |&lt;br /&gt;+------------+----------+-----------+----------+&lt;/pre&gt;&lt;/li&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-8073706158260972785?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8073706158260972785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8073706158260972785'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/initialize-upon-first-use.html' title='initialize upon the first use'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2791582304690658053</id><published>2008-10-18T16:11:00.001-07:00</published><updated>2008-10-18T16:11:46.163-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><title type='text'>bit operation again SRM 422</title><content type='html'>&lt;p&gt;&lt;img height="1" alt="" src="http://www.topcoder.com/i/clear.gif" width="10" border="0"&gt;&lt;br&gt;topcder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=10036"&gt;BirthdayCake &lt;/a&gt; &lt;p&gt;用gcc的__builtin_popcount()速度快了两倍多。&lt;/p&gt; &lt;p&gt;由于cake 那个是50位的，用了long long，然后调用__builtin_popcount两次分别处理高低32位然后求和。注意给常数1加上LL后缀。&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// couting 1's&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; count_bit(&lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; n) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; __builtin_popcount(n&amp;gt;&amp;gt;32) + __builtin_popcount(n &amp;amp;((1LL&amp;lt;&amp;lt;32)-1LL));&lt;br /&gt;}&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; checkmax(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &amp;amp;a, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; b) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(a &amp;lt; b) a = b;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; BirthdayCake::howManyFriends(vector &amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; availableFruits, vector &amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; f, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; K) {&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N = availableFruits.size(); &lt;span style="color: #008000"&gt;// total number of available fruit&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m = f.size(); &lt;span style="color: #008000"&gt;// friend number&lt;/span&gt;&lt;br /&gt;    map&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; fruit;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; N; ++i)&lt;br /&gt;        fruit.insert(make_pair(availableFruits[i], fruit.size()));&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; mask = (1LL&amp;lt;&amp;lt;N)-1LL;&lt;br /&gt;    vector&amp;lt;&lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt;&amp;gt; like(m, mask);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;        stringstream ss;&lt;br /&gt;        ss &amp;lt;&amp;lt; f[i];&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; tmp;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(ss &amp;gt;&amp;gt; tmp) { &lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(!fruit.count(tmp)) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;            like[i] &amp;amp;= ~(1LL&amp;lt;&amp;lt; fruit[tmp]); &lt;span style="color: #008000"&gt;// clear uliked bits&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; max = (1&amp;lt;&amp;lt;(m))-1; &lt;span style="color: #008000"&gt;// all friends included&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; maxnf = 0; &lt;span style="color: #008000"&gt;// max number of friends included&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// brute force traversal of all subsets&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = max; i &amp;gt;=0 ; --i) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; cake = mask;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; m; ++j) &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( i &amp;amp; (1&amp;lt;&amp;lt;j) ) {&lt;br /&gt;            cake &amp;amp;= like[j];&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( count_bit(cake) &amp;lt; K )&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;goto&lt;/span&gt; next;&lt;br /&gt;        }&lt;br /&gt;        checkmax(maxnf, count_bit(i));&lt;br /&gt;next:   &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; maxnf;&lt;br /&gt;}&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2791582304690658053?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2791582304690658053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2791582304690658053'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/bit-operation-again-srm-422.html' title='bit operation again SRM 422'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-4373345096238417330</id><published>2008-10-17T17:57:00.001-07:00</published><updated>2008-10-18T16:42:23.116-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='divide and conquer'/><category scheme='http://www.blogger.com/atom/ns#' term='sweeping'/><title type='text'>closest pair problem</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;a href="http://en.wikipedia.org/wiki/Closest_pair_of_points_problem"&gt;Closest pair of points problem on wiki&lt;/a&gt;  &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/K-nearest_neighbor_algorithm"&gt;nearest neighbor problem&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Kd-tree"&gt;k-d tree on wiki&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Sweeping: &lt;a title="http://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPair1D.html" href="http://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPair1D.html"&gt;http://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPair1D.html&lt;a href="http://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPairApplet/ClosestPairApplet.html"&gt;&lt;img style="margin: 0px 60px 0px 20px" height="291" alt="image" src="http://lh5.ggpht.com/greeness/SPlICqVZL5I/AAAAAAAAB8s/BhVwWVnh3XY/image%5B13%5D.png" width="286" align="right"&gt;&lt;a href="http://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPairApplet/ClosestPairApplet.html"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 0px 0px 20px; border-right-width: 0px" height="298" alt="image" src="http://lh6.ggpht.com/greeness/SPlIDNDkNOI/AAAAAAAAB8w/5VEBUTO9ah4/image%5B12%5D.png" width="106" align="right" border="0"&gt;&lt;/a&gt;&lt;/a&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;every time the sweep line encounters a point &lt;i&gt;p&lt;/i&gt;, we will perform the following actions:  &lt;ol&gt; &lt;li&gt;Remove the points further than &lt;i&gt;d&lt;/i&gt; to the left of &lt;i&gt;p&lt;/i&gt; from the ordered set &lt;i&gt;D&lt;/i&gt; that is storing the points in the strip.&amp;nbsp;&amp;nbsp; &lt;li&gt;Determine the point on the left of &lt;i&gt;p&lt;/i&gt; that is closest to it  &lt;li&gt;If the distance between this point and &lt;i&gt;p&lt;/i&gt; is less than &lt;i&gt;d&lt;/i&gt; (the current minimum distance), then update the closest current pair and &lt;i&gt;d&lt;/i&gt;. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;The summary and analysis of the plane sweep algorithm goes something like this:  &lt;ul&gt; &lt;li&gt;sort the set according to &lt;i&gt;x&lt;/i&gt;-coordinates (this is necessary for a plane sweep approach to determine the coordinates of the next point), which takes O(&lt;i&gt;n&lt;/i&gt;log&lt;i&gt;n&lt;/i&gt;) time  &lt;li&gt;inserting and removing each point once from the ordered set &lt;i&gt;D&lt;/i&gt; (each insertion takes O(log&lt;i&gt;n&lt;/i&gt;) time as shown in the section on (2,4)-trees), which takes a total of O(&lt;i&gt;n&lt;/i&gt;log&lt;i&gt;n&lt;/i&gt;) time  &lt;li&gt;comparing each point to a constant number of its neighbors (which takes O(&lt;i&gt;n&lt;/i&gt;) time in total )&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;K-D Tree&lt;/p&gt; &lt;p&gt;Animation: &lt;a title="http://donar.umiacs.umd.edu/quadtree/points/kdtree.html" href="http://donar.umiacs.umd.edu/quadtree/points/kdtree.html"&gt;http://donar.umiacs.umd.edu/quadtree/points/kdtree.html&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;Complexity&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;Building a static &lt;i&gt;k&lt;/i&gt;d-tree from &lt;i&gt;n&lt;/i&gt; points takes &lt;a href="http://en.wikipedia.org/wiki/Big_O_notation"&gt;O&lt;/a&gt;(&lt;i&gt;n&lt;/i&gt; log &lt;sup&gt;2&lt;/sup&gt; &lt;i&gt;n&lt;/i&gt;) time if an &lt;a href="http://en.wikipedia.org/wiki/Big_O_notation"&gt;O&lt;/a&gt;(&lt;i&gt;n&lt;/i&gt; log &lt;i&gt;n&lt;/i&gt;) sort is used to compute the median at each level. The complexity is &lt;a href="http://en.wikipedia.org/wiki/Big_O_notation"&gt;O&lt;/a&gt;(&lt;i&gt;n&lt;/i&gt; log &lt;i&gt;n&lt;/i&gt;) if a linear &lt;a href="http://en.wikipedia.org/wiki/Selection_algorithm"&gt;median-finding&lt;/a&gt; algorithm such as the one described in Cormen &lt;i&gt;et al&lt;/i&gt;&lt;sup&gt;&lt;a href="http://en.wikipedia.org/wiki/Kd-tree#cite_note-2"&gt;[3]&lt;/a&gt;&lt;/sup&gt; is used. &lt;/li&gt;&lt;/ul&gt; &lt;ul&gt; &lt;li&gt;Inserting a new point into a balanced &lt;i&gt;k&lt;/i&gt;d-tree takes O(log &lt;i&gt;n&lt;/i&gt;) time.  &lt;li&gt;Removing a point from a balanced &lt;i&gt;k&lt;/i&gt;d-tree takes O(log &lt;i&gt;n&lt;/i&gt;) time.  &lt;li&gt;Querying an axis-parallel range in a balanced &lt;i&gt;k&lt;/i&gt;d-tree takes O(&lt;i&gt;n&lt;/i&gt;&lt;sup&gt;1-1/d&lt;/sup&gt; +&lt;i&gt;k&lt;/i&gt;) time, where k is the number of the reported points, and d the dimension of the &lt;i&gt;k&lt;/i&gt;d-tree.  &lt;li&gt;Finding the nearest point is an O(log N) operation.&lt;/li&gt;&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-4373345096238417330?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4373345096238417330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4373345096238417330'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/closest-pair-problem.html' title='closest pair problem'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/greeness/SPlICqVZL5I/AAAAAAAAB8s/BhVwWVnh3XY/s72-c/image%5B13%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-5383710543846545347</id><published>2008-10-17T15:13:00.001-07:00</published><updated>2008-10-17T15:13:51.417-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><title type='text'>Bit operations hacks</title><content type='html'>&lt;p&gt;I find a few more interesting sites:&lt;/p&gt; &lt;h4&gt;&lt;/h4&gt; &lt;p&gt;&lt;a href="http://graphics.stanford.edu/~seander/bithacks.html"&gt;Bit Twiddling Hacks&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;a href="http://aggregate.org/MAGIC/#Absolute%20Value%20of%20a%20Float"&gt;The Aggregate Magic Algorithms&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-5383710543846545347?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5383710543846545347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5383710543846545347'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/bit-operations-hacks.html' title='Bit operations hacks'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1058622857568295491</id><published>2008-10-16T19:18:00.001-07:00</published><updated>2008-10-16T21:36:15.291-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='design patterns'/><title type='text'>Design Patterns (4) - Factory method and Abstract Factory</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Factory_method_pattern"&gt;Factory method&lt;a href="http://lh6.ggpht.com/greeness/SPgQG7L-0DI/AAAAAAAAB8Y/OKGtl_1ERSA/image%5B6%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; margin: 0px 0px 0px 10px; border-left: 0px; border-bottom: 0px" height="98" alt="image" src="http://lh3.ggpht.com/greeness/SPgQHArmEOI/AAAAAAAAB8c/6jrwf02W3mM/image_thumb%5B3%5D.png" width="478" align="right" border="0"&gt;&lt;/a&gt;&lt;/a&gt;&lt;br&gt;Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.  &lt;p&gt;&amp;nbsp; &lt;p&gt;&lt;strong&gt;&lt;a href="http://www.exforsys.com/tutorials/csharp/creational-design-patterns.html"&gt;Why would anybody use such a design pattern?&lt;/a&gt;&lt;/strong&gt; &lt;p&gt;Imagine you are writing the code for the “Client” object. The “client” object needs to use the “Product” object. You hard code the object creation process in the “Client” Now any changes in the object creation procedure would mean that you need to change the “client” too. The sole purpose of the “Factory” object is to create “Product” This gives us a certain amount of flexibility. The “client” delegates that task to “Factory”. Any changes in the object creation process do not affect the “client” and changes to “Factory” should be fairly simple as that is the only thing it does. &lt;p&gt;ref: &lt;a title="http://vorleakchy.wordpress.com/2008/08/15/factory-method-design-pattern/" href="http://vorleakchy.wordpress.com/2008/08/15/factory-method-design-pattern/"&gt;http://vorleakchy.wordpress.com/2008/08/15/factory-method-design-pattern/&lt;/a&gt; &lt;p&gt;Principles:  &lt;p&gt;No variable should hold a reference to&amp;nbsp; a concrete class. If you use new, you' ll be holding a reference to a concrete class. Use a factory to get around that!  &lt;p&gt;No class should derive from a concrete class. If you derive from a concret class, you're depending on a concrete class. Derive from an abstraction, like an interface or an abstract class.  &lt;p&gt;No method should override an implemented method of any its base class.&amp;nbsp; If you override an implemented method, then your base class wasn't really an abstraction to start with. Those methods implemented in the base class are meant to be shared by all your subclasses.&lt;a href="http://lh3.ggpht.com/greeness/SPf13hyB0AI/AAAAAAAAB8Q/kQZuAkr6LtE/image%5B5%5D.png"&gt;&lt;img style="margin: 15px 0px 0px 15px" height="220" alt="image" src="http://lh5.ggpht.com/greeness/SPf14Ha5wRI/AAAAAAAAB8U/AmMqQ9_hjtM/image_thumb%5B3%5D.png" width="556" align="right"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;My simple factory method example:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;//Pizza example:&lt;br /&gt;&lt;br /&gt;#include &amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Pizza {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; get_price() = 0;&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HamAndMushroomPizza: &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Pizza {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; get_price(){&lt;br /&gt;        std::cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;Ham and Mushroom: $8.5&lt;/span&gt;" &amp;lt;&amp;lt; std::endl;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DeluxePizza : &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Pizza {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; get_price() {&lt;br /&gt;        std::cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;Deluxe: $10.5&lt;/span&gt;" &amp;lt;&amp;lt; std::endl;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SeafoodPizza : &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Pizza {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; get_price(){&lt;br /&gt;        std::cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;Seafood: $11.5&lt;/span&gt;" &amp;lt;&amp;lt; std::endl;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; PizzaFactory {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Pizza* create_pizza(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; type) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (type == "&lt;span style="color: #8b0000"&gt;Ham and Mushroom&lt;/span&gt;")&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HamAndMushroomPizza();&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (type == "&lt;span style="color: #8b0000"&gt;Seafood Pizza&lt;/span&gt;")&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SeafoodPizza();&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DeluxePizza();&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #008000"&gt;//usage&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;    PizzaFactory factory;&lt;br /&gt;    Pizza *pz = factory.create_pizza("&lt;span style="color: #8b0000"&gt;Default&lt;/span&gt;");&lt;br /&gt;    pz-&amp;gt;get_price();&lt;br /&gt; &lt;br /&gt;    Pizza *ph = factory.create_pizza("&lt;span style="color: #8b0000"&gt;Ham and Mushroom&lt;/span&gt;");&lt;br /&gt;    ph-&amp;gt;get_price();&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; pz;&lt;br /&gt;    pz = factory.create_pizza("&lt;span style="color: #8b0000"&gt;Seafood Pizza&lt;/span&gt;");&lt;br /&gt; &lt;br /&gt;    pz-&amp;gt;get_price();&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; pz;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; ph;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1058622857568295491?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1058622857568295491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1058622857568295491'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/design-patterns-4-factory-method-and.html' title='Design Patterns (4) - Factory method and Abstract Factory'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/greeness/SPgQHArmEOI/AAAAAAAAB8c/6jrwf02W3mM/s72-c/image_thumb%5B3%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-6335179380755373352</id><published>2008-10-16T18:00:00.001-07:00</published><updated>2008-10-16T18:01:27.960-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='design patterns'/><title type='text'>Design Patterns (3) - Decorator</title><content type='html'>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;Decorator&lt;/a&gt;: Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality. &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/greeness/SPfjvWnrs5I/AAAAAAAAB78/IWqaU56MWBY/image%5B51%5D.png"&gt;&lt;img style="margin: 0px 30px 0px 20px" height="317" alt="image" src="http://lh6.ggpht.com/greeness/SPfjvsA8hhI/AAAAAAAAB8A/075GXvKvdz0/image_thumb%5B43%5D.png" width="385" align="right"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The idea:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Start with a basic component and "decorate" it with condiments at runtime.&lt;/li&gt; &lt;li&gt;Decorators have the same supertype as the objects they decorate.&lt;/li&gt; &lt;li&gt;Given that the decorator has the same supertype as the object it decorates, we can pass around a decorated object in place of the original object.&lt;/li&gt; &lt;li&gt;The decorator adds its own behavior either before and/or after delegating to the object it decorates to do the rest of the job.&lt;/li&gt; &lt;li&gt;Objects can be decorated at any time, so we can decorate objects dynamically at runtime with as many decorators as we like.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;a href="http://lh4.ggpht.com/greeness/SPfjwC1gmEI/AAAAAAAAB8E/s5qKeb5t9ig/image%5B50%5D.png"&gt;&lt;img height="579" alt="image" src="http://lh6.ggpht.com/greeness/SPfj5wJ3yQI/AAAAAAAAB8M/vFZY8zsUrtQ/image_thumb%5B42%5D.png" width="685"&gt;&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-6335179380755373352?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/6335179380755373352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/6335179380755373352'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/design-patterns-3-decorator.html' title='Design Patterns (3) - Decorator'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/greeness/SPfjvsA8hhI/AAAAAAAAB8A/075GXvKvdz0/s72-c/image_thumb%5B43%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-7689739392912721376</id><published>2008-10-16T16:24:00.000-07:00</published><updated>2008-10-16T16:25:22.224-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='design patterns'/><title type='text'>Design Patterns (2) - Observer</title><content type='html'>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Observer_pattern"&gt;Observer&lt;/a&gt; :&lt;a href="http://lh6.ggpht.com/greeness/SPfKE3nXe6I/AAAAAAAAB7k/mOowtRN6FE4/image%5B10%5D.png"&gt;&lt;img style="margin: 0px 40px 0px 30px" height="287" alt="image" src="http://lh6.ggpht.com/greeness/SPfKFO5eM2I/AAAAAAAAB7o/cJXrrwPM0Zo/image_thumb%5B8%5D.png" width="384" align="right"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.&lt;/p&gt; &lt;p&gt;Design principles of Observer ( from head first Design Pattern Chap 2)&lt;/p&gt; &lt;ol&gt; &lt;li&gt;The thing that varies in the Observer Pattern is the state of the Subject and the number and types of Observers. With this pattern, you can vary the objects that are dependent on the state of the Subject, without having to change that Subject. That's called planning ahead!  &lt;li&gt;Both the Subject and Observer use interfaces. the subject keeps track of objects implementing the Observer interface, while the observers register with, and get notified by the Subject interface. As we've seen, this keeps things nice and &lt;strong&gt;loosely coupled&lt;/strong&gt;.  &lt;li&gt;The Observer Pattern uses composition to compose any number of Observers with their Subjects. These relationships aren't set up by some kind of inheritance hierarchy. No, they are set up at runtime by &lt;strong&gt;composition&lt;/strong&gt;!&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;wiki's c++ example shows an implementation of head first's chap 2 problem. It is a nice example.&lt;/p&gt; &lt;p&gt;Just refer to it for deep understanding of the pattern.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-7689739392912721376?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/7689739392912721376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/7689739392912721376'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/design-patterns-2-observer_16.html' title='Design Patterns (2) - Observer'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/greeness/SPfKFO5eM2I/AAAAAAAAB7o/cJXrrwPM0Zo/s72-c/image_thumb%5B8%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-5705057254803565716</id><published>2008-10-16T14:49:00.001-07:00</published><updated>2008-10-16T19:53:37.823-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='design patterns'/><title type='text'>Design Patterns (1) - Strategy</title><content type='html'>&lt;p&gt;book reference:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Gang-of-four: Design Patterns  &lt;li&gt;Head first design patterns&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;resource reference:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Software_design_pattern"&gt;wiki - design pattern&lt;/a&gt;  &lt;li&gt;&lt;a href="http://sourcemaking.com/design-patterns"&gt;source-making&lt;/a&gt;  &lt;li&gt;&lt;a title="http://www.dofactory.com/Patterns/Patterns.aspx" href="http://www.dofactory.com/Patterns/Patterns.aspx"&gt;http://www.dofactory.com/Patterns/Patterns.aspx&lt;/a&gt;  &lt;li&gt;&lt;a title="http://blog.cumps.be/design-patterns-strategy-pattern/" href="http://blog.cumps.be/design-patterns-strategy-pattern/"&gt;http://blog.cumps.be/design-patterns-strategy-pattern/&lt;/a&gt; &lt;li&gt;&lt;a title="http://www.patterndepot.com/put/8/JavaPatterns.htm" href="http://www.patterndepot.com/put/8/JavaPatterns.htm"&gt;http://www.patterndepot.com/put/8/JavaPatterns.htm&lt;/a&gt; &lt;li&gt;&lt;a title="http://www.codeguru.com/forum/showthread.php?t=327982" href="http://www.codeguru.com/forum/showthread.php?t=327982"&gt;http://www.codeguru.com/forum/showthread.php?t=327982&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Strategy Pattern:&lt;/p&gt; &lt;p&gt;Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The &lt;strong&gt;Context&lt;/strong&gt; &lt;u&gt;has-a&lt;/u&gt; behavior of &lt;strong&gt;Strategy,&lt;/strong&gt; which can be implemented with different algorithms.  &lt;li&gt;We define a private member in &lt;strong&gt;Context&lt;/strong&gt;: a pointer to the general superclass &lt;strong&gt;Strategy&lt;/strong&gt;.  &lt;li&gt;We have a &lt;strong&gt;set_strategy&lt;/strong&gt; method in &lt;strong&gt;Context&lt;/strong&gt; class to change behavior at runtime.  &lt;li&gt;We also have a superclass: &lt;strong&gt;Strategy&lt;/strong&gt; and a bunch of subclass : &lt;strong&gt;ConcreteStrategy&lt;/strong&gt; to implement the behavior.  &lt;li&gt;In client code, we have one or multiple instances of &lt;strong&gt;Context.&lt;/strong&gt;  &lt;li&gt;At any given time, only one &lt;strong&gt;ConcreteStrategy&lt;/strong&gt; is availabe to be executed a single &lt;strong&gt;Context&lt;/strong&gt; object.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Strategy Pattern example:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/Diagrams/strategy.gif"&gt;&lt;img style="margin: 0px 35px 0px 0px" height="190" alt="image" src="http://lh3.ggpht.com/greeness/SPe3AuI9ZfI/AAAAAAAAB7g/900YT5HxGMY/image%5B20%5D.png" width="507" align="right"&gt;&lt;/a&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; StrategyInterface&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; execute() = 0;&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ConcreteStrategyA: &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; StrategyInterface&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; execute()&lt;br /&gt;        {&lt;br /&gt;            cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;Called ConcreteStrategyA execute method&lt;/span&gt;" &amp;lt;&amp;lt; endl;&lt;br /&gt;        }&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ConcreteStrategyB: &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; StrategyInterface&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; execute()&lt;br /&gt;        {&lt;br /&gt;            cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;Called ConcreteStrategyB execute method&lt;/span&gt;" &amp;lt;&amp;lt; endl;&lt;br /&gt;        }&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ConcreteStrategyC: &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; StrategyInterface&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; execute()&lt;br /&gt;        {&lt;br /&gt;            cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;Called ConcreteStrategyC execute method&lt;/span&gt;" &amp;lt;&amp;lt; endl;&lt;br /&gt;        }&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Context&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt;:&lt;br /&gt;        StrategyInterface *_strategy;&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;        Context(StrategyInterface *strategy):_strategy(strategy)&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; set_strategy(StrategyInterface *strategy) &lt;br /&gt;        {&lt;br /&gt;            _strategy = strategy;&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; execute() &lt;br /&gt;        {&lt;br /&gt;            _strategy-&amp;gt;execute();&lt;br /&gt;        }&lt;br /&gt;};&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; argc, &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *argv[])&lt;br /&gt;{&lt;br /&gt;    ConcreteStrategyA concreteStrategyA;&lt;br /&gt;    ConcreteStrategyB concreteStrategyB;&lt;br /&gt;    ConcreteStrategyC concreteStrategyC;&lt;br /&gt;&lt;br /&gt;    Context contextA(&amp;amp;concreteStrategyA);&lt;br /&gt;    Context contextB(&amp;amp;concreteStrategyB);&lt;br /&gt;    Context contextC(&amp;amp;concreteStrategyC);&lt;br /&gt; &lt;br /&gt;    contextA.execute();&lt;br /&gt;    contextB.execute();&lt;br /&gt;    contextC.execute();&lt;br /&gt;&lt;br /&gt;    contextA.set_strategy(&amp;amp;concreteStrategyB);&lt;br /&gt;    contextA.execute();&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-5705057254803565716?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5705057254803565716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5705057254803565716'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/design-patterns-strategy.html' title='Design Patterns (1) - Strategy'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/greeness/SPe3AuI9ZfI/AAAAAAAAB7g/900YT5HxGMY/s72-c/image%5B20%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-3959689391229516334</id><published>2008-10-14T22:40:00.000-07:00</published><updated>2008-10-14T23:24:20.284-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux programming'/><title type='text'>interprocess communication IPC (2) - shared memory</title><content type='html'>&lt;pre&gt;I use the IPC-shared memory to help solve UVa problem 495: fib freeze.&lt;/pre&gt;&lt;pre&gt;The same algorithm is ranked 3rd ! &lt;/pre&gt;&lt;pre&gt;The idea is as follows:&lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt; the main process fork a child to precompute the Fib numbers up to 5000.&lt;/li&gt;&lt;br /&gt;&lt;li&gt; the main process at the same time read in all input n!&lt;/li&gt;&lt;br /&gt;&lt;li&gt; as soon as the child finish, main process begin table-lookup and output&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the shared memory is a char [][], each char[] contains a factorial for the corresponding n&lt;/li&gt;&lt;br /&gt;&lt;li&gt;i use semaphore (here actually act as a mutex) to synchronize the shared memory access&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;the child process get resource and release until it finishes computing 5000!&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the main process then access the resource to lookup the result&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;pre&gt;The program flow:&lt;/pre&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;shmget&lt;/strong&gt;: to request a shared memory block from the system&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;shmat&lt;/strong&gt;: to link the pointer to the shared memory &lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;semget&lt;/strong&gt;: to create a semaphore (IPC_CREAT)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;semctl&lt;/strong&gt;: to initialize the semaphore (SET_VAL)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;fork&lt;/strong&gt;: to generate a child process&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;semop&lt;/strong&gt;: to use semaphore to maintain the resource access&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;semctl&lt;/strong&gt;: to remove semaphore ( IPC_RMID)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;shmdt&lt;/strong&gt;: to detatch the pointer from the shared memory&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;shmctl&lt;/strong&gt;: to delete the shared memory ( IPC_RMID)&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;shmget很容易出错,如果是异常退出，可能需要更换key，重新run, （考虑用ipcrm -m #shmid kill)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;最大可分配的memory及相关的参数可在man shmget中找到&lt;/p&gt;&lt;br /&gt;&lt;p&gt;e.g., /proc/sys/kernal/shmmax&amp;nbsp; maximum memory &lt;/p&gt;&lt;pre&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;#include &amp;lt;sys/shm.h&amp;gt;&lt;br /&gt;#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/ipc.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/sem.h&amp;gt;&lt;/pre&gt;&lt;pre&gt;#include "BigInt.h"&lt;/pre&gt;&lt;pre&gt;#define MAXSZ  5000&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; databuf {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; memo [MAXSZ+1][1050];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; argc, &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *argv[])&lt;br /&gt;{&lt;br /&gt;    key_t key = 0x18845;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; shmid;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; semid;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; mode;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;/* make the key: */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;/*&lt;br /&gt;    if ((key = ftok("plotter.c", 'R')) == -1) {&lt;br /&gt;        perror("ftok");&lt;br /&gt;        exit(1);&lt;br /&gt;	}*/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;/* connect to (and possibly create) the segment: */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((shmid = shmget(key, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(databuf), 0600 |IPC_CREAT)) == -1) {&lt;br /&gt;      printf("&lt;span style="color: #8b0000"&gt;shmid %d %d\n&lt;/span&gt;", shmid,errno);&lt;br /&gt;      perror("&lt;span style="color: #8b0000"&gt;shmget&lt;/span&gt;");&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;switch&lt;/span&gt;(errno) {&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; EACCES:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;access permit\n&lt;/span&gt;");&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; EEXIST:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;segment exist\n&lt;/span&gt;"); &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; EINVAL:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;einval\n&lt;/span&gt;");&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; ENFILE:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;enfile\n&lt;/span&gt;");&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; ENOENT:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;enoent\n&lt;/span&gt;");&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; ENOMEM:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;no memory\n&lt;/span&gt;");&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; ENOSPC:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;enospc\n&lt;/span&gt;");&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; EPERM:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;eperm\n&lt;/span&gt;");&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;default&lt;/span&gt;:&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;other\n&lt;/span&gt;");&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;      }      &lt;br /&gt;	&lt;br /&gt;      exit(1);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #008000"&gt;/* attach to the segment to get a pointer to it: */&lt;/span&gt;&lt;br /&gt;    databuf* data = (databuf*)shmat(shmid, (&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; *)0, 0);&lt;br /&gt;      &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (data == (databuf *)(-1)) {&lt;br /&gt;        perror("&lt;span style="color: #8b0000"&gt;shmat&lt;/span&gt;");&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #008000"&gt;//memset(data, 0, sizeof(data));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; sembuf P = {0, -1, 0};  &lt;span style="color: #008000"&gt;/* set to allocate resource */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; sembuf V = {0, 1, 0}; &lt;span style="color: #008000"&gt;/* free resource */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;/*&lt;br /&gt;    if ((key = ftok("fibfreeze.c", 'J')) == -1) {&lt;br /&gt;        perror("ftok");&lt;br /&gt;        exit(1);&lt;br /&gt;	}*/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;/* create a semaphore set with 1 semaphore: */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((semid = semget(0x99543, 1, 0666 | IPC_CREAT)) == -1) {&lt;br /&gt;        perror("&lt;span style="color: #8b0000"&gt;semget&lt;/span&gt;");&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #008000"&gt;//printf("sem id %d\n", semid);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;/* initialize semaphore #0 to 1: */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (semctl(semid, 0, SETVAL, 1) == -1) {&lt;br /&gt;        perror("&lt;span style="color: #8b0000"&gt;semctl&lt;/span&gt;");&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    pid_t kid = fork();&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(kid  == 0) {&lt;br /&gt;      &lt;span style="color: #008000"&gt;//printf("kid process \n");&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: #008000"&gt;//kid process, computer fib number up to 5000&lt;/span&gt;&lt;br /&gt;      BigInt a1(0), a2(1), a;&lt;br /&gt;      semop(semid, &amp;amp;P, 1);&lt;br /&gt;      strcpy(data-&amp;gt;memo[0], "&lt;span style="color: #8b0000"&gt;0&lt;/span&gt;");&lt;br /&gt;      strcpy(data-&amp;gt;memo[1], "&lt;span style="color: #8b0000"&gt;1&lt;/span&gt;");&lt;br /&gt;      &lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 2; i &amp;lt;= MAXSZ; ++i){&lt;br /&gt;	    a = a1 + a2;&lt;br /&gt;	    strcpy(data-&amp;gt;memo[i], a.toString().c_str());&lt;br /&gt;	    &lt;span style="color: #008000"&gt;//printf("calc m[%d]=%s\n", i, data-&amp;gt;memo[i] );&lt;/span&gt;&lt;br /&gt;	    &lt;span style="color: #008000"&gt;//printf("calc %d, len %d\n", i, strlen(data-&amp;gt;memo[i]));&lt;/span&gt;&lt;br /&gt;	    a1 = a2;&lt;br /&gt;	    a2 = a;&lt;br /&gt;      }&lt;br /&gt;      semop(semid, &amp;amp;V, 1);&lt;br /&gt;      exit(0);&lt;br /&gt;    } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {&lt;br /&gt;      &lt;span style="color: #008000"&gt;//printf("parent process\n");&lt;/span&gt;&lt;br /&gt;      std::vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; n;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; tmp;&lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;tmp) != EOF)&lt;br /&gt;	    n.push_back(tmp);&lt;br /&gt;          &lt;br /&gt;      &lt;span style="color: #008000"&gt;//wait();&lt;/span&gt;&lt;br /&gt;      semop(semid, &amp;amp;P, 1);&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N = n.size();&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; N; ++i)&lt;br /&gt;	    printf("&lt;span style="color: #8b0000"&gt;The Fibonacci number for %d is %s\n&lt;/span&gt;", n[i], data-&amp;gt;memo[n[i]]);&lt;br /&gt;      semop(semid, &amp;amp;V, 1);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: #008000"&gt;/* remove semaphore */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (semctl(semid, 0, IPC_RMID, 0) == -1) {&lt;br /&gt;      perror("&lt;span style="color: #8b0000"&gt;semctl&lt;/span&gt;");&lt;br /&gt;      exit(1);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #008000"&gt;//printf("free semaphores done\n");&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;/* detach from the segment: */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (shmdt(data) == -1) {&lt;br /&gt;        perror("&lt;span style="color: #8b0000"&gt;shmdt&lt;/span&gt;");&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #008000"&gt;/* remove shared memory */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (shmctl(shmid, IPC_RMID, 0) == -1) {&lt;br /&gt;       perror("&lt;span style="color: #8b0000"&gt;shmctl shmid&lt;/span&gt;");&lt;br /&gt;       exit(1);&lt;br /&gt;    }    &lt;br /&gt;    &lt;span style="color: #008000"&gt;//printf("free memory segment done\n");&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-3959689391229516334?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3959689391229516334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3959689391229516334'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/interprocess-communication-ipc-2-shared.html' title='interprocess communication IPC (2) - shared memory'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2781742639943289361</id><published>2008-10-14T12:57:00.000-07:00</published><updated>2008-10-15T21:44:54.308-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux programming'/><title type='text'>interprocess communication IPC (1) - message queue</title><content type='html'>&lt;a href="http://www.ecst.csuchico.edu/%7Ebeej/guide/ipc/"&gt;Beej's Guide&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.linuxinsight.com/advanced_linux_programming_interprocess_communication.html"&gt;Advanced Linux Programming&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;IPC methods:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Signal&lt;/li&gt;&lt;li&gt;Pipe&lt;/li&gt;&lt;li&gt;Named Pipe&lt;/li&gt;&lt;li&gt;Message Queue&lt;/li&gt;&lt;li&gt;Shared Memory&lt;/li&gt;&lt;/ul&gt;Message Queue:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/* use ftok(...) to generate a key */&lt;br /&gt;/* key_t ftok(const char* path, int id) */&lt;br /&gt;&lt;br /&gt;key_t key = ftok("/home/someone/somefile", 'b');&lt;br /&gt;&lt;br /&gt;/* create or connect to an existing queue */&lt;br /&gt;/* int msgget(key_t key, int msgflg) */&lt;br /&gt;/* 666 -&gt; rw-rw-rw- */&lt;br /&gt;int msqid = msgget(key, 0666|IPC_CREAT);&lt;br /&gt;&lt;br /&gt;/* each message is made up of two parts */&lt;br /&gt;/* mtype is set to any positive number as a message type */&lt;br /&gt;/* mdata is any data struct that will be added to the queue */&lt;br /&gt;   struct pirate_msgbuf {&lt;br /&gt;       long mtype;  /* must be positive */&lt;br /&gt;       char name[30];&lt;br /&gt;       char ship_type;&lt;br /&gt;       int notoriety;&lt;br /&gt;       int cruelty;&lt;br /&gt;       int booty_value;&lt;br /&gt;   };&lt;br /&gt;&lt;br /&gt;/* pass the message to the queue */&lt;br /&gt;/* int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);&lt;br /&gt;struct pirate_msgbuf pmb = {2, "L'Olonais", 'S', 80, 10, 12035};&lt;br /&gt;msgsnd(msqid, &amp;amp;pmb, sizeof(pmb), 0);&lt;br /&gt;&lt;br /&gt;/* retrieve message from the queue */&lt;br /&gt;struct pirate_msgbuf pmrecv;&lt;br /&gt;/*  int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); */&lt;br /&gt;msgrcv(msqid, &amp;amp;pmrecv, sizeof(pmb), 2, 0);&lt;br /&gt;&lt;br /&gt;/* destroy a message queue */&lt;br /&gt;msgctl(msqid, IPC_RMID, NULL);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;beej's guide provides a pair of nice example source&lt;br /&gt;&lt;a href="http://www.ecst.csuchico.edu/%7Ebeej/guide/ipc/kirk.c"&gt;kirk.c&lt;/a&gt;  &lt;a href="http://www.ecst.csuchico.edu/%7Ebeej/guide/ipc/spock.c"&gt;spock.c&lt;/a&gt;&lt;br /&gt;start kirk and spock, you can send text through kirk and receive them through spock.&lt;br /&gt;Also you can try to add mtype to enable multiple kirks and spocks. &lt;br /&gt;&lt;br /&gt;Here is a little piece of code of my test:&lt;br /&gt;I am using fork() to create a kid process to read characters from stdin,&lt;br /&gt;then using the parent process to simulate running a simple algorithm based on the message read by kid.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;/* interprocess communication: Message Queue */&lt;br /&gt;&lt;br /&gt;#include &lt; stdio.h &gt;&lt;br /&gt;#include &lt; stdlib.h &gt;&lt;br /&gt;#include &lt; ctype.h &gt;&lt;br /&gt;#include &lt; sys/ipc.h &gt;&lt;br /&gt;#include &lt; sys/msg.h &gt;&lt;br /&gt;#include &lt; unistd.h &gt;&lt;br /&gt;#include &lt; time.h &gt;&lt;br /&gt;&lt;br /&gt;const int ARR_SIZE = 8;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;struct mymsgbuf{&lt;br /&gt;  long mtype; // a positive integer: &lt;br /&gt;  int a[ARR_SIZE];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int main(int argc, char* argv[]) {&lt;br /&gt;&lt;br /&gt;  int N = 0;&lt;br /&gt;  if(argc &lt; 2)&lt;br /&gt;    N = 100;&lt;br /&gt;  else &lt;br /&gt;    N = atoi(argv[1]);&lt;br /&gt;&lt;br /&gt;  printf("number of computations = %d\n", N*N);&lt;br /&gt;&lt;br /&gt;  key_t key = ftok("ab.", 'm');&lt;br /&gt;  int msgq_id; // message queue id&lt;br /&gt;&lt;br /&gt;  //initializes a new message queue&lt;br /&gt;  if((msgq_id = msgget(key, IPC_CREAT|0660)) == -1) {&lt;br /&gt;    printf("msgget error\n");&lt;br /&gt;    exit(1);&lt;br /&gt;  } else {&lt;br /&gt;    printf("msg queue id %d created\n", msgq_id);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  if(fork() == 0) {&lt;br /&gt;    printf("this is child process\n");&lt;br /&gt;    mymsgbuf qbuf;&lt;br /&gt;    qbuf.mtype = 1;&lt;br /&gt;    &lt;br /&gt;    int j = 0;&lt;br /&gt;    while(!feof(stdin)) {&lt;br /&gt;      for(int i = 0; i &lt; ARR_SIZE; ++i) {&lt;br /&gt; scanf("%d ", &amp;qbuf.a[i]);&lt;br /&gt;      }&lt;br /&gt;      if((msgsnd(msgq_id, &amp;qbuf, sizeof(mymsgbuf)-sizeof(long), 0)) == -1) {&lt;br /&gt; printf("error in msgsnd\n");&lt;br /&gt; exit(1);&lt;br /&gt;      }&lt;br /&gt;      ++j;&lt;br /&gt;    }&lt;br /&gt;    // the last message &lt;br /&gt;    // use mtype = 2 to notify the parent process&lt;br /&gt;    qbuf.mtype = 2;&lt;br /&gt;    msgsnd(msgq_id, &amp;qbuf, sizeof(mymsgbuf)-sizeof(long),0);&lt;br /&gt;    printf("send %d\n", j);&lt;br /&gt;    return 0;&lt;br /&gt;  } else { // in parent process&lt;br /&gt;    printf("this is parent process\n");&lt;br /&gt;    mymsgbuf qbuf;&lt;br /&gt;    int j = 0;&lt;br /&gt;    while(msgrcv(msgq_id, &amp;qbuf, 200, 0, 0)) {&lt;br /&gt;      if(qbuf.mtype == 2) break;&lt;br /&gt;&lt;br /&gt;      int total = 0;&lt;br /&gt;      int t = N;&lt;br /&gt;&lt;br /&gt;      /* just doing some work */&lt;br /&gt;      while(t--) {&lt;br /&gt; for(int i = 0; i &lt; ARR_SIZE; ++i)&lt;br /&gt;   for(int k = 0; k &lt; ARR_SIZE; ++k)&lt;br /&gt;     total += qbuf.a[i] * qbuf.a[k];&lt;br /&gt;      }&lt;br /&gt;      ++j;&lt;br /&gt;    }&lt;br /&gt;    wait(); // wait until the child process finish&lt;br /&gt;    printf("recv %d\n", j);&lt;br /&gt;    msgctl(msgq_id, IPC_RMID, 0); // delete the message queue&lt;br /&gt;    printf("msg q removed\n");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // printf("time taken %d\n", clock()-startt);&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;running output:time ./msgq 100 &lt; tmp&lt;br /&gt;number of computations = 10000&lt;br /&gt;msg queue id 557057 created&lt;br /&gt;this is child process&lt;br /&gt;this is parent process&lt;br /&gt;send 39036&lt;br /&gt;recv 39036&lt;br /&gt;msg q removed&lt;br /&gt;&lt;br /&gt;real    0m1.452s&lt;br /&gt;user    0m1.384s&lt;br /&gt;sys     0m0.064s&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2781742639943289361?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2781742639943289361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2781742639943289361'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/interprocess-communication-ipc.html' title='interprocess communication IPC (1) - message queue'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2362273927875314097</id><published>2008-10-13T20:16:00.001-07:00</published><updated>2008-10-13T20:51:06.410-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>C++ notes</title><content type='html'>&lt;h5&gt;From Wikipedia, the free encyclopedia&lt;/h5&gt; &lt;ul&gt; &lt;li&gt;&lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Auto_ptr"&gt;auto_ptr&lt;/a&gt;&lt;/b&gt;  &lt;ul&gt; &lt;li&gt;&lt;b&gt;auto_ptr&lt;/b&gt; is a &lt;a href="http://en.wikipedia.org/wiki/Template_%28programming%29"&gt;template&lt;/a&gt; class available in the &lt;a href="http://en.wikipedia.org/wiki/C%2B%2B"&gt;C++&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/C%2B%2B_standard_library"&gt;Standard Library&lt;/a&gt; (declared in &lt;b&gt;&amp;lt;memory&amp;gt;&lt;/b&gt;) that provides some basic &lt;a href="http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization"&gt;RAII&lt;/a&gt; features for &lt;a href="http://en.wikipedia.org/wiki/Pointer_%28computing%29#C_and_C.2B.2B"&gt;C++ raw pointers&lt;/a&gt;.  &lt;p&gt;The auto_ptr template class describes an object that stores a pointer to an allocated object of type Type* that ensures that the object to which it points gets destroyed automatically when control leaves a scope.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Resource_acquisition_is_initialization"&gt;Resource Acquisition Is Initialization&lt;/a&gt; (RAII)  &lt;ul&gt; &lt;li&gt;The acquisition is typically bound to the construction (initialization) and the automatic, deterministic destruction (uninitialization) is used to guarantee the resource is released. Since scoped objects are cleaned up regardless of whether the scope exits through normal use or through an exception, RAII is a key concept for writing &lt;a href="http://en.wikipedia.org/wiki/Exception-safe"&gt;exception-safe&lt;/a&gt; code.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Virtual_inheritance"&gt;virtual inheritance&lt;/a&gt;&lt;/b&gt;  &lt;ul&gt; &lt;li&gt;In the &lt;a href="http://en.wikipedia.org/wiki/C%2B%2B"&gt;C++&lt;/a&gt; programming language, &lt;b&gt;virtual inheritance&lt;/b&gt; is a kind of &lt;a href="http://en.wikipedia.org/wiki/Inheritance_%28computer_science%29"&gt;inheritance&lt;/a&gt; that solves some of the problems caused by &lt;a href="http://en.wikipedia.org/wiki/Multiple_inheritance"&gt;multiple inheritance&lt;/a&gt; (particularly the "&lt;a href="http://en.wikipedia.org/wiki/Diamond_problem"&gt;diamond problem&lt;/a&gt;") by clarifying ambiguity over which ancestor class members to use.  &lt;li&gt;&lt;a title="http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.9" href="http://c++-faq-lite/multiple-inheritance.html#faq-25.9"&gt;c++-faq-lite&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;tt&gt;&lt;a href="http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10"&gt;placement new&lt;/a&gt;&lt;/tt&gt;  &lt;ul&gt; &lt;li&gt;The simplest use is to place an object at a particular location in memory. This is done by supplying the place as a pointer parameter to the &lt;tt&gt;new&lt;/tt&gt; part of a &lt;tt&gt;new&lt;/tt&gt; expression.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;volatile keyword&lt;/li&gt; &lt;ul&gt; &lt;li&gt;&lt;a title="http://www.embedded.com/story/OEG20010615S0107" href="http://www.embedded.com/story/OEG20010615S0107"&gt;http://www.embedded.com/story/OEG20010615S0107&lt;/a&gt; &lt;li&gt;&lt;a title="http://www.redhat.com/docs/manuals/enterprise/RHEL-3-Manual/gcc/volatiles.html" href="http://www.redhat.com/docs/manuals/enterprise/RHEL-3-Manual/gcc/volatiles.html"&gt;http://www.redhat.com/docs/manuals/enterprise/RHEL-3-Manual/gcc/volatiles.html&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Data_structure_alignment"&gt;Data structure alignment&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2362273927875314097?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2362273927875314097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2362273927875314097'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/c-notes.html' title='C++ notes'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1038136732771050793</id><published>2008-10-12T15:08:00.001-07:00</published><updated>2008-10-12T15:08:23.457-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>numeric_limits</title><content type='html'>&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;limits&amp;gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() { &lt;br /&gt;&lt;br /&gt;    cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;max(short): &lt;/span&gt;" &amp;lt;&amp;lt; numeric_limits&amp;lt;&lt;span style="color: #0000ff"&gt;short&lt;/span&gt;&amp;gt;::max() &amp;lt;&amp;lt; endl;&lt;br /&gt;    cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;max(int):   &lt;/span&gt;" &amp;lt;&amp;lt; numeric_limits&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;::max() &amp;lt;&amp;lt; endl;&lt;br /&gt;    cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;max(long long):  &lt;/span&gt;" &amp;lt;&amp;lt; numeric_limits&amp;lt;&lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt;&amp;gt;::max() &amp;lt;&amp;lt; endl;&lt;br /&gt;    cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;max(unsigned long long):  &lt;/span&gt;" &amp;lt;&amp;lt; numeric_limits&amp;lt;&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt;&amp;gt;::max() &amp;lt;&amp;lt; endl; &lt;br /&gt;&lt;br /&gt;    cout &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;max(double):  &lt;/span&gt;" &amp;lt;&amp;lt; numeric_limits&amp;lt;&lt;span style="color: #0000ff"&gt;double&lt;/span&gt;&amp;gt;::max() &amp;lt;&amp;lt; endl; &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;/pre&gt;&lt;pre&gt;output:&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;max(short): 32767&lt;br&gt;max(int):&amp;nbsp;&amp;nbsp; 2147483647&lt;br&gt;max(long long):&amp;nbsp; 9223372036854775807&lt;br&gt;max(unsigned long long):&amp;nbsp; 18446744073709551615&lt;br&gt;max(double):&amp;nbsp; 1.79769e+308&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1038136732771050793?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1038136732771050793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1038136732771050793'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/numericlimits.html' title='numeric_limits'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2137928620692006227</id><published>2008-10-12T15:07:00.001-07:00</published><updated>2008-10-12T15:07:27.423-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>C++ FAQ Lite</title><content type='html'>&lt;h5&gt;&lt;a title="http://www.parashift.com/c++-faq-lite/" href="http://www.parashift.com/c++-faq-lite/"&gt;http://www.parashift.com/c++-faq-lite/&lt;/a&gt;&lt;/h5&gt; &lt;h3&gt;[18] Const correctness&lt;/h3&gt; &lt;p&gt;Constness means using the keyword &lt;tt&gt;const&lt;/tt&gt; to prevent &lt;tt&gt;const&lt;/tt&gt; objects from getting mutated. Declaring the &lt;tt&gt;const&lt;/tt&gt;-ness of a parameter is just another form of type safety.&lt;/p&gt; &lt;p&gt;For example, if you wanted to create a function &lt;tt&gt;f()&lt;/tt&gt; that accepted a &lt;tt&gt;std::string&lt;/tt&gt;, plus you want to promise callers not to change the caller's &lt;tt&gt;std::string&lt;/tt&gt; that gets passed to &lt;tt&gt;f()&lt;/tt&gt;, you can have &lt;tt&gt;f()&lt;/tt&gt; receive its &lt;tt&gt;std::string&lt;/tt&gt; parameter...  &lt;ul&gt; &lt;li&gt;&lt;tt&gt;void f1(const std::string&amp;amp; s);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/tt&gt;&lt;em&gt;// Pass by reference-to-&lt;tt&gt;const&lt;/tt&gt;&lt;/em&gt;  &lt;li&gt;&lt;tt&gt;void f2(const std::string* sptr);&amp;nbsp; &lt;/tt&gt;&lt;em&gt;// Pass by pointer-to-&lt;tt&gt;const&lt;/tt&gt;&lt;/em&gt;  &lt;li&gt;&lt;tt&gt;void f3(std::string s);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/tt&gt;&lt;em&gt;// Pass by value&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You have to read pointer declarations right-to-left.  &lt;ul&gt; &lt;li&gt;&lt;tt&gt;const Fred* p&lt;/tt&gt; means "&lt;tt&gt;p&lt;/tt&gt; points to a &lt;tt&gt;Fred&lt;/tt&gt; that is &lt;tt&gt;const&lt;/tt&gt;" — that is, the &lt;tt&gt;Fred&lt;/tt&gt; object can't be changed &lt;a href="http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.16"&gt;via &lt;tt&gt;p&lt;/tt&gt;&lt;/a&gt;.  &lt;li&gt;&lt;tt&gt;Fred* const p&lt;/tt&gt; means "&lt;tt&gt;p&lt;/tt&gt; is a &lt;tt&gt;const&lt;/tt&gt; pointer to a &lt;tt&gt;Fred&lt;/tt&gt;" — that is, you can change the &lt;tt&gt;Fred&lt;/tt&gt; object &lt;a href="http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.16"&gt;via &lt;tt&gt;p&lt;/tt&gt;&lt;/a&gt;, but you can't change the pointer &lt;tt&gt;p&lt;/tt&gt; itself.  &lt;li&gt;&lt;tt&gt;const Fred* const p&lt;/tt&gt; means "&lt;tt&gt;p&lt;/tt&gt; is a &lt;tt&gt;const&lt;/tt&gt; pointer to a &lt;tt&gt;const&lt;/tt&gt; &lt;tt&gt;Fred&lt;/tt&gt;" — that is, you can't change the pointer &lt;tt&gt;p&lt;/tt&gt; itself, nor can you change the &lt;tt&gt;Fred&lt;/tt&gt; object &lt;a href="http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.16"&gt;via &lt;tt&gt;p&lt;/tt&gt;&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt; &lt;h5&gt;"&lt;tt&gt;const&lt;/tt&gt; member function" inspects (rather than mutates) its object.&lt;/h5&gt; &lt;h5&gt;"&lt;tt&gt;const&lt;/tt&gt;-overloading"&lt;/h5&gt; &lt;p&gt;&lt;tt&gt;class Fred { ... };&lt;br&gt;class MyFredList {&lt;br&gt;public:&lt;br&gt;&amp;nbsp;&amp;nbsp; const Fred&amp;amp; operator[] (unsigned index) const;&amp;nbsp; &lt;/tt&gt;&lt;em&gt;&lt;small&gt;&lt;big&gt;←&lt;/big&gt; subscript operators often come in pairs&lt;/small&gt;&lt;/em&gt;&lt;tt&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; Fred&amp;amp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operator[] (unsigned index);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/tt&gt;&lt;em&gt;&lt;small&gt;&lt;big&gt;←&lt;/big&gt; subscript operators often come in pairs&lt;/small&gt;&lt;/em&gt;&lt;tt&gt;&lt;br&gt;&lt;/tt&gt;&lt;em&gt;&lt;small&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/small&gt;&lt;/em&gt;&lt;tt&gt;&lt;br&gt;}; &lt;/tt&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2137928620692006227?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2137928620692006227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2137928620692006227'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/c-faq-lite.html' title='C++ FAQ Lite'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1186433998764912928</id><published>2008-10-10T23:29:00.001-07:00</published><updated>2008-10-15T21:27:13.996-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux programming'/><title type='text'>POSIX Thread</title><content type='html'>A nice posix thread &lt;a href="https://computing.llnl.gov/tutorials/pthreads/"&gt;tutorial&lt;/a&gt;.&lt;br /&gt;Also google a pdf pthread tutorial by Peter Chapin.&lt;br /&gt;&lt;br /&gt;Here I am trying to do a very trivial UVa problem: 11172 Relational Operators using multi-threading.&lt;br /&gt;But UVa compiler does not do g++ -pthread. We just play here instead of submission. :)&lt;br /&gt;Two threads:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;the first thread read fron stdin&lt;/li&gt;&lt;li&gt;the second thread compare the two numbers and output&lt;/li&gt;&lt;li&gt;both thread access the two buffers using semaphore to synchronize&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;pre&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;pthread.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;sys/ipc.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;sys/sem.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;errno.h&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; MYDATA{&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; a;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; b;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;MYDATA data[&lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; sembuf p1 = {&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;}; &lt;span style=' color: Green;'&gt;// request buf 0&lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; sembuf p2 = {&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;}; &lt;span style=' color: Green;'&gt;// request buf 1&lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; sembuf v1 = {&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;};  &lt;span style=' color: Green;'&gt;// release buf 0&lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; sembuf v2 = {&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;};  &lt;span style=' color: Green;'&gt;// release buf 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; ndata;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; semid;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;void&lt;/span&gt;* read(&lt;span style=' color: Blue;'&gt;void&lt;/span&gt;*) {&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; c = ndata;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;while&lt;/span&gt;(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;    scanf(&lt;span style=' color: Maroon;'&gt;"%d %d "&lt;/span&gt;, &amp;amp;data[&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;].a, &amp;amp;data[&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;].b);&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("read %d %d, c %d \n", data[0].a, data[0].b, c);&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(c-- == &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) &lt;span style=' color: Blue;'&gt;break&lt;/span&gt;;&lt;br /&gt;    semop(semid, &amp;amp;v1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    &lt;br /&gt;    semop(semid, &amp;amp;p2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    scanf(&lt;span style=' color: Maroon;'&gt;"%d %d "&lt;/span&gt;, &amp;amp;data[&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;].a, &amp;amp;data[&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;].b);&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("read %d %d, c %d \n", data[1].a, data[1].b, c);&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(c--==&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) &lt;span style=' color: Blue;'&gt;break&lt;/span&gt;;&lt;br /&gt;    semop(semid, &amp;amp;v2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);  &lt;br /&gt;    semop(semid, &amp;amp;p1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;  }&lt;br /&gt;  &lt;span style=' color: Green;'&gt;//printf("read thread end\n");&lt;/span&gt;&lt;br /&gt;  pthread_exit((&lt;span style=' color: Blue;'&gt;void&lt;/span&gt;*)&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;inline&lt;/span&gt; &lt;span style=' color: Blue;'&gt;void&lt;/span&gt; cmp(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; a, &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; b) {&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(a &amp;gt; b) printf(&lt;span style=' color: Maroon;'&gt;"&amp;gt;\n"&lt;/span&gt;);&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;else&lt;/span&gt; &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(a &amp;lt; b) printf(&lt;span style=' color: Maroon;'&gt;"&amp;lt;\n"&lt;/span&gt;);&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;else&lt;/span&gt; printf(&lt;span style=' color: Maroon;'&gt;"=\n"&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;void&lt;/span&gt;* compare(&lt;span style=' color: Blue;'&gt;void&lt;/span&gt;*) {&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; c = ndata;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;while&lt;/span&gt;(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//semop(semid, &amp;amp;p2, 1);&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("compare %d %d \n", data[1].a, data[1].b);&lt;/span&gt;&lt;br /&gt;    cmp(data[&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;].a, data[&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;].b);&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(c-- == &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) &lt;span style=' color: Blue;'&gt;break&lt;/span&gt;;&lt;br /&gt;    semop(semid, &amp;amp;v2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    &lt;br /&gt;    semop(semid, &amp;amp;p1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("compare %d %d \n", data[0].a, data[0].b);    &lt;/span&gt;&lt;br /&gt;    cmp(data[&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;].a, data[&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;].b);&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(c--==&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) &lt;span style=' color: Blue;'&gt;break&lt;/span&gt;;&lt;br /&gt;    semop(semid, &amp;amp;v1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    semop(semid, &amp;amp;p2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;  }&lt;br /&gt;  pthread_exit((&lt;span style=' color: Blue;'&gt;void&lt;/span&gt;*)&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; main() {&lt;br /&gt;  pthread_attr_t attr;&lt;br /&gt;   &lt;br /&gt;  &lt;span style=' color: Green;'&gt;/* create threads */&lt;/span&gt;&lt;br /&gt;  pthread_attr_init(&amp;amp;attr);&lt;br /&gt;  pthread_attr_setdetachstate(&amp;amp;attr, PTHREAD_CREATE_JOINABLE);&lt;br /&gt;  &lt;br /&gt;  scanf(&lt;span style=' color: Maroon;'&gt;"%d "&lt;/span&gt;, &amp;amp;ndata);&lt;br /&gt;  scanf(&lt;span style=' color: Maroon;'&gt;"%d %d "&lt;/span&gt;, &amp;amp;data[&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;].a, &amp;amp;data[&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;].b);&lt;br /&gt;  ndata --;&lt;br /&gt;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;((semid = semget(&lt;span style=' color: Maroon;'&gt;0x3332&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0600&lt;/span&gt; |IPC_CREAT)) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;    perror(&lt;span style=' color: Maroon;'&gt;"semget"&lt;/span&gt;);&lt;br /&gt;    exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(semctl(semid, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, SETVAL, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;    perror(&lt;span style=' color: Maroon;'&gt;"semctl"&lt;/span&gt;);&lt;br /&gt;    exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(semctl(semid, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, SETVAL, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;    perror(&lt;span style=' color: Maroon;'&gt;"semctl"&lt;/span&gt;);&lt;br /&gt;    exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  pthread_t readThd, compareThd;&lt;br /&gt;  pthread_create(&amp;amp;readThd, &amp;amp;attr, read, (&lt;span style=' color: Blue;'&gt;void&lt;/span&gt;*)&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;);&lt;br /&gt;  pthread_create(&amp;amp;compareThd, &amp;amp;attr, compare, (&lt;span style=' color: Blue;'&gt;void&lt;/span&gt;*)&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;void&lt;/span&gt; * status;&lt;br /&gt;  pthread_join(readThd, &amp;amp;status);&lt;br /&gt;  pthread_join(compareThd, &amp;amp;status);&lt;br /&gt;  &lt;br /&gt;  pthread_exit(&lt;span style=' color: Blue;'&gt;NULL&lt;/span&gt;);  &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The IPC shared memory version is as follows:&lt;br /&gt;&lt;pre&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;sys/shm.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;errno.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;sys/ipc.h&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;sys/sem.h&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; databuf {&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; a1;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; b1;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; a2;&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; b2;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;inline&lt;/span&gt; &lt;span style=' color: Blue;'&gt;void&lt;/span&gt; cmp(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; a, &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; b) {&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(a &amp;gt; b) printf(&lt;span style=' color: Maroon;'&gt;"&amp;gt;\n"&lt;/span&gt;);&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;else&lt;/span&gt; &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(a &amp;lt; b) printf(&lt;span style=' color: Maroon;'&gt;"&amp;lt;\n"&lt;/span&gt;);&lt;br /&gt;  &lt;span style=' color: Blue;'&gt;else&lt;/span&gt; printf(&lt;span style=' color: Maroon;'&gt;"=\n"&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; main(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; argc, &lt;span style=' color: Blue;'&gt;char&lt;/span&gt; *argv[])&lt;br /&gt;{&lt;br /&gt;    key_t key = &lt;span style=' color: Maroon;'&gt;0x18875&lt;/span&gt;;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; shmid;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; semid;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; mode;&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/* make the key: */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/*&lt;br /&gt;    if ((key = ftok("plotter.c", 'R')) == -1) {&lt;br /&gt;        perror("ftok");&lt;br /&gt;        exit(1);&lt;br /&gt;    }*/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/* connect to (and possibly create) the segment: */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; ((shmid = shmget(key, &lt;span style=' color: Blue;'&gt;sizeof&lt;/span&gt;(databuf), &lt;span style=' color: Maroon;'&gt;0600&lt;/span&gt; |IPC_CREAT)) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;      perror(&lt;span style=' color: Maroon;'&gt;"shmget"&lt;/span&gt;);&lt;br /&gt;      exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/* attach to the segment to get a pointer to it: */&lt;/span&gt;&lt;br /&gt;    databuf* data = (databuf*)shmat(shmid, (&lt;span style=' color: Blue;'&gt;void&lt;/span&gt; *)&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;);&lt;br /&gt;      &lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (data == (databuf *)(-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;)) {&lt;br /&gt;        perror(&lt;span style=' color: Maroon;'&gt;"shmat"&lt;/span&gt;);&lt;br /&gt;        exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//memset(data, 0, sizeof(data));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; sembuf p1 = {&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;};  &lt;span style=' color: Green;'&gt;/* set to allocate resource */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; sembuf p2 = {&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;};&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; sembuf v1 = {&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;}; &lt;span style=' color: Green;'&gt;/* free resource */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;struct&lt;/span&gt; sembuf v2 = {&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;};&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/*&lt;br /&gt;    if ((key = ftok("fibfreeze.c", 'J')) == -1) {&lt;br /&gt;        perror("ftok");&lt;br /&gt;        exit(1);&lt;br /&gt;    }*/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/* create a semaphore set with 1 semaphore: */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; ((semid = semget(&lt;span style=' color: Maroon;'&gt;0x1543&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;, &lt;span style=' color: Maroon;'&gt;0666&lt;/span&gt; | IPC_CREAT)) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;        perror(&lt;span style=' color: Maroon;'&gt;"semget"&lt;/span&gt;);&lt;br /&gt;        exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("sem id %d\n", semid);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/* initialize semaphore #0 to 1: */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (semctl(semid, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, SETVAL, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;        perror(&lt;span style=' color: Maroon;'&gt;"semctl"&lt;/span&gt;);&lt;br /&gt;        exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (semctl(semid, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, SETVAL, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;        perror(&lt;span style=' color: Maroon;'&gt;"semctl"&lt;/span&gt;);&lt;br /&gt;        exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; ndata;&lt;br /&gt;    scanf(&lt;span style=' color: Maroon;'&gt;"%d "&lt;/span&gt;, &amp;amp;ndata);&lt;br /&gt;    scanf(&lt;span style=' color: Maroon;'&gt;"%d %d "&lt;/span&gt;, &amp;amp;(data-&amp;gt;a2), &amp;amp;(data-&amp;gt;b2));&lt;br /&gt;    &lt;br /&gt;    pid_t kid = fork();&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(kid  == &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) {&lt;br /&gt;      &lt;span style=' color: Blue;'&gt;while&lt;/span&gt;(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(feof(stdin)) {&lt;br /&gt;      semop(semid, &amp;amp;v1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;      &lt;span style=' color: Blue;'&gt;break&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;    scanf(&lt;span style=' color: Maroon;'&gt;"%d %d "&lt;/span&gt;, &amp;amp;data-&amp;gt;a1, &amp;amp;data-&amp;gt;b1);&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("read %d %d \n", data-&amp;gt;a1, data-&amp;gt;b1);&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    semop(semid, &amp;amp;v1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    semop(semid, &amp;amp;p2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(feof(stdin)) {&lt;br /&gt;      semop(semid, &amp;amp;v2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;      &lt;span style=' color: Blue;'&gt;break&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;    scanf(&lt;span style=' color: Maroon;'&gt;"%d %d "&lt;/span&gt;, &amp;amp;data-&amp;gt;a2, &amp;amp;data-&amp;gt;b2);&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("read %d %d \n", data-&amp;gt;a2, data-&amp;gt;b2);&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    semop(semid, &amp;amp;v2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);  &lt;br /&gt;    semop(semid, &amp;amp;p1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;      }&lt;br /&gt;      &lt;span style=' color: Green;'&gt;//printf("kid exit\n");&lt;/span&gt;&lt;br /&gt;      exit(&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;);&lt;br /&gt;    } &lt;span style=' color: Blue;'&gt;else&lt;/span&gt; {&lt;br /&gt;      &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; c = ndata;&lt;br /&gt;      &lt;span style=' color: Blue;'&gt;while&lt;/span&gt;(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("cmp %d %d, c %d\n", data-&amp;gt;a2, data-&amp;gt;b2, c);&lt;/span&gt;&lt;br /&gt;    cmp(data-&amp;gt;a2, data-&amp;gt;b2);&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(--c ==&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) &lt;span style=' color: Blue;'&gt;break&lt;/span&gt;;&lt;br /&gt;    semop(semid, &amp;amp;v2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    semop(semid, &amp;amp;p1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("cmp %d %d, c %d\n", data-&amp;gt;a1, data-&amp;gt;b1, c);&lt;/span&gt;&lt;br /&gt;    cmp(data-&amp;gt;a1, data-&amp;gt;b1);&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(--c ==&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) &lt;span style=' color: Blue;'&gt;break&lt;/span&gt;;&lt;br /&gt;    semop(semid, &amp;amp;v1, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    semop(semid, &amp;amp;p2, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span style=' color: Green;'&gt;/* remove semaphore */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (semctl(semid, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, IPC_RMID, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;      perror(&lt;span style=' color: Maroon;'&gt;"semctl"&lt;/span&gt;);&lt;br /&gt;      exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("free semaphores done\n");&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/* detach from the segment: */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (shmdt(data) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;        perror(&lt;span style=' color: Maroon;'&gt;"shmdt"&lt;/span&gt;);&lt;br /&gt;        exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Green;'&gt;/* remove shared memory */&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (shmctl(shmid, IPC_RMID, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) == -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) {&lt;br /&gt;       perror(&lt;span style=' color: Maroon;'&gt;"shmctl shmid"&lt;/span&gt;);&lt;br /&gt;       exit(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }    &lt;br /&gt;    &lt;span style=' color: Green;'&gt;//printf("free memory segment done\n");&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;;&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1186433998764912928?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1186433998764912928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1186433998764912928'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/posix-thread.html' title='POSIX Thread'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-5603056628718668912</id><published>2008-10-10T20:33:00.000-07:00</published><updated>2008-10-14T05:10:32.228-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><title type='text'>RPN and evaluation tree</title><content type='html'>First, here is a very good article on "&lt;a href="http://www.arstdesign.com/articles/expression_evaluation.html"&gt;An expression evaluator&lt;/a&gt;" with source code. It also gives detailed introduction on RPN (Reverse Polish Notation).&lt;br /&gt;Here is the algorithm to parse in RPN's manner:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;for each char of the expression&lt;br /&gt;  decide if the char is part of an operand or of an operator&lt;br /&gt;  if the char is part of an operand,&lt;br /&gt;    append it to the list of operands&lt;br /&gt;  else if the char is part of an operator,&lt;br /&gt;    look up the operator&lt;br /&gt;  match it with supported operators&lt;br /&gt;  compare operator with the preceding operators&lt;br /&gt;  if this operator is prevalent,&lt;br /&gt;    store the operator in a stack&lt;br /&gt;    otherwise, unstack the preceding operator,&lt;br /&gt;               append the preceding operator to the list of operands&lt;br /&gt;               stack the new operator&lt;br /&gt;  end if&lt;br /&gt;  end if&lt;br /&gt;end for&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation"&gt;Wiki&lt;/a&gt;'s article on RPN.&lt;br /&gt;&lt;br /&gt;For example: an math expression:  9+8x5-20^3&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;list 1 (operand)      | list 2 (operator)&lt;br /&gt;9                     |&lt;br /&gt;9                     | +                      &lt;br /&gt;9 8                   | +&lt;br /&gt;9 8                   | + x ( x has precedence over +, so just append x)&lt;br /&gt;9 8 5                 | + x&lt;br /&gt;9 8 5 x               | + - ( x has precedence over -, so remove x, append x to operand list, then  append - to operator list)&lt;br /&gt;9 8 5 x 20            | + -&lt;br /&gt;9 8 5 x 20            | + - ^ (of course, ^ has precedence over -, just append ^ on operator list)&lt;br /&gt;9 8 5 x 20 3          | + - ^&lt;br /&gt;9 8 5 x 20 3 ^        | + - (now start from the tail, remove all elements from operator list and append then to the operand list one by one)&lt;br /&gt;9 8 5 x 20 3 ^ -      | +&lt;br /&gt;9 8 5 x 20 3 ^ - +    |&lt;br /&gt;&lt;br /&gt;RPN parsing done!&lt;br /&gt;&lt;br /&gt;Calculation starts from the left, push elements onto calc stack.&lt;br /&gt;Whenever you get one operator, do the calculation immediately. push the result onto the stack.&lt;br /&gt;&lt;br /&gt;Calculation stack     | comment&lt;br /&gt;9                     |&lt;br /&gt;9 8 5 x               | 8 x 5 = 40&lt;br /&gt;9 40                  |&lt;br /&gt;9 40 20               |&lt;br /&gt;9 40 20 3             |&lt;br /&gt;9 40 20 3 ^           | 20 ^ 3 = 8000&lt;br /&gt;9 40 8000             |&lt;br /&gt;9 40 8000 -           | 40 - 8000 = -7960&lt;br /&gt;9 -7960               |&lt;br /&gt;9 -7960 +             | 9 + (-7960) = -7951&lt;br /&gt;-7951&lt;br /&gt;&lt;br /&gt;done! so 9+8x5-20^3 = -7951&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Problem UVa 288: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;page=show_problem&amp;problem=224"&gt;Arithmetic Operations With Large Integers&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I used &lt;a href="http://shygypsy.com/tools/BigInt.cpp"&gt;BigInt library &lt;/a&gt;from shygypsy.com&lt;br /&gt;Just modified the operator ^ to support "&lt;a href="http://en.wikipedia.org/wiki/Exponentiating_by_squaring"&gt;repeated squaring&lt;/a&gt;". &lt;br /&gt;i.e., &lt;br /&gt;&lt;pre name="code" class="c++"&gt;&lt;br /&gt;BigInt BigInt::operator^  (BigInt n){&lt;br /&gt;  &lt;br /&gt;  BigInt result = 1;&lt;br /&gt;  BigInt base = *this;&lt;br /&gt;  while(n &gt; 0) {&lt;br /&gt;    if(n % 2 == 1) {&lt;br /&gt;      result *= base;&lt;br /&gt;    }&lt;br /&gt;    base *= base;&lt;br /&gt;    n /= 2;&lt;br /&gt;  }&lt;br /&gt;    &lt;br /&gt;  return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// operator precedence&lt;br /&gt;// + - 2+3-4-5+4, use left -&gt; right&lt;br /&gt;// 2*3*4*5, use left-&gt;right&lt;br /&gt;// 6^7^8^9, use right-&gt;left&lt;br /&gt;bool precedence(int z1, int z2) {&lt;br /&gt;  if(z1 == -10) return true;&lt;br /&gt;  if(z2 == -10) return false;&lt;br /&gt;&lt;br /&gt;  if(z1 == z2) return false;&lt;br /&gt;  if(z1 == -5) return true;&lt;br /&gt;  if(z2 == -5) return false;&lt;br /&gt;  return false;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;char buff[35000];&lt;br /&gt;int main() {&lt;br /&gt;  while(gets(buff) &amp;&amp; !feof(stdin)) {&lt;br /&gt;    string b(buff);&lt;br /&gt;    // since op is positive, we use &lt;br /&gt;    // - negative integer to represent operator, &lt;br /&gt;    // - positive integer to represent operand&lt;br /&gt;   &lt;br /&gt;    // so we define&lt;br /&gt;    //   **  = ^ = -10&lt;br /&gt;    //   *   = -5&lt;br /&gt;    //   + = -1&lt;br /&gt;    //   - = -2&lt;br /&gt; &lt;br /&gt;    deque&lt;BigInt&gt; number;&lt;br /&gt;    deque&lt;int&gt; op;&lt;br /&gt;    int pos = 0;&lt;br /&gt;    for(int i = 0; i &lt; b.size(); ++i) {&lt;br /&gt;      if(b[i]&gt;='0' &amp;&amp; b[i]&lt;='9') continue;&lt;br /&gt;&lt;br /&gt;      // append previous numbers&lt;br /&gt;      number.push_back(BigInt(b.substr(pos, i-pos).c_str()));&lt;br /&gt;      &lt;br /&gt;      int v;&lt;br /&gt;      // power has highest priority&lt;br /&gt;      if(b[i]=='*' &amp;&amp; b[i+1] == '*') {&lt;br /&gt; v = -10;&lt;br /&gt; ++i;&lt;br /&gt;      } else {&lt;br /&gt; if(b[i] == '*') v = -5;&lt;br /&gt; else if(b[i] == '+') v = -1;&lt;br /&gt;&lt;br /&gt; else if(b[i] == '-') v = -2;&lt;br /&gt;&lt;br /&gt; if(!op.empty() &amp;&amp; !precedence(v, op.back())) {&lt;br /&gt;   number.push_back(BigInt(op.back()));&lt;br /&gt;   op.pop_back();&lt;br /&gt; }&lt;br /&gt;      }&lt;br /&gt; &lt;br /&gt;      op.push_back(v);&lt;br /&gt;      pos = i + 1;&lt;br /&gt;    }&lt;br /&gt;    // append the last number&lt;br /&gt;    number.push_back(BigInt(b.substr(pos).c_str()));&lt;br /&gt;    &lt;br /&gt;    while(!op.empty()) {&lt;br /&gt;      number.push_back(BigInt(op.back()));&lt;br /&gt;      op.pop_back();&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /*&lt;br /&gt;    deque&lt;BigInt&gt; tmp(number);&lt;br /&gt;    while(!tmp.empty()){&lt;br /&gt;      cout &lt;&lt; tmp.front()&lt;&lt; " ";&lt;br /&gt;      tmp.pop_front();&lt;br /&gt;    }&lt;br /&gt;    printf("\n");*/&lt;br /&gt;&lt;br /&gt;    // parse into reverse polish format   &lt;br /&gt;    stack&lt;BigInt&gt; calc;&lt;br /&gt;    while(!number.empty()) {&lt;br /&gt;      BigInt t = number.front();&lt;br /&gt;      number.pop_front();&lt;br /&gt;&lt;br /&gt;      // t is an operator&lt;br /&gt;      if( t &lt; 0) {&lt;br /&gt; BigInt right = calc.top(); calc.pop();&lt;br /&gt; BigInt left = calc.top();  calc.pop();&lt;br /&gt; BigInt res;&lt;br /&gt; if(t == -1) res = left+right;&lt;br /&gt; else if(t == -2) res = left-right;&lt;br /&gt; else if(t == -5) res = left*right;&lt;br /&gt; else res = left^right;&lt;br /&gt;&lt;br /&gt; calc.push(res);&lt;br /&gt;      } else {&lt;br /&gt; calc.push(t);&lt;br /&gt;      }&lt;br /&gt;    }  &lt;br /&gt;    cout &lt;&lt; calc.top()&lt;&lt; endl;&lt;br /&gt;  } &lt;br /&gt;  return 0;  &lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-5603056628718668912?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5603056628718668912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5603056628718668912'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/rpn-and-evaluation-tree.html' title='RPN and evaluation tree'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1745435294433197976</id><published>2008-10-09T17:41:00.001-07:00</published><updated>2008-10-09T17:46:19.117-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='recursion'/><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><title type='text'>Tree Recovery</title><content type='html'>&lt;p&gt;Problem UVa: 536 - &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;page=show_problem&amp;amp;problem=477"&gt;Tree Recovery&lt;/a&gt;&lt;/p&gt; &lt;p&gt;给了pre-order 和 in-order traversal 序列，要求输出post-order &lt;/p&gt; &lt;p&gt;The idea behind the code below is this: &lt;br&gt;1) The root is first element of the pre-order traversal &lt;br&gt;2) Everything left of the root in the in-order traversal belongs to the left subtree. Similarly everything to the right belongs to the right subtree. &lt;br&gt;3) The children of the current root are the first elements of the sub-pre-order-traversals. &lt;br&gt;4) recurse and put the numbers of the children in an array &lt;br&gt;5) recurse in post-order traversal through the new tree &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;/* 536 - Tree Recovery */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;/* recursion */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; preorder[30];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; inorder[30];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; recover(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x1, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y1, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x2, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y2) {&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; t = preorder[x1];&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(x1 == y1) {&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt;%c&lt;/span&gt;", t);&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;br /&gt;    }  &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// locate the root position in in-order &lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// which split the travel seq into two halves&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pos;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = x2; i &amp;lt;= y2; ++i)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(inorder[i] == t) {&lt;br /&gt;            pos = i;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p = x1+pos-x2;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;    &lt;span style="color: #008000"&gt;// visit left sub-tree&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(pos-1 &amp;gt;= x2)&lt;br /&gt;        recover(x1+1, p , x2, pos-1);&lt;br /&gt;    &lt;span style="color: #008000"&gt;// visit right sub-tree&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(y2 &amp;gt;= pos+1)&lt;br /&gt;        recover(p+1, y1, pos+1, y2);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// postorder -&amp;gt; print root at last&lt;/span&gt;&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;%c&lt;/span&gt;", t);&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(scanf("&lt;span style="color: #8b0000"&gt;%s %s &lt;/span&gt;",preorder, inorder) != EOF) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; L = strlen(preorder) - 1;&lt;br /&gt;        recover(0, L, 0, L); &lt;span style="color: #008000"&gt;// first &amp;lt;0,L&amp;gt; is preorder index, second &amp;lt;0,L&amp;gt; is in-order index&lt;/span&gt;&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt;\n&lt;/span&gt;");&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;Problem UVa: 10410 &lt;a href="http://acm.uva.es/p/v104/10410.html"&gt;Tree Reconstruction&lt;/a&gt;&lt;/pre&gt;&lt;pre&gt;给了BFS和DFS traversal序列，要输出每个节点和它相应的叶子结点&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1745435294433197976?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1745435294433197976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1745435294433197976'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/tree-recovery.html' title='Tree Recovery'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1076542910759361186</id><published>2008-10-09T07:20:00.001-07:00</published><updated>2008-10-09T08:58:43.873-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jobhunting'/><title type='text'>Skill keywords in IT job-seeking website</title><content type='html'>&lt;ul&gt; &lt;li&gt;.Net  &lt;li&gt;Algorithm  &lt;li&gt;AJAX  &lt;li&gt;ASP  &lt;li&gt;ASP.net  &lt;li&gt;Analyst  &lt;li&gt;C  &lt;li&gt;C#  &lt;li&gt;Data Structure  &lt;li&gt;Design Pattern  &lt;li&gt;CSS  &lt;li&gt;Database Design  &lt;li&gt;DB2/UDB  &lt;li&gt;DHTML  &lt;li&gt;HTML  &lt;li&gt;J2EE  &lt;li&gt;JAVA  &lt;li&gt;JDBC  &lt;li&gt;JSP  &lt;li&gt;NetBeans  &lt;li&gt;OOP  &lt;li&gt;Oracle  &lt;li&gt;Performance Tuning  &lt;li&gt;Perl  &lt;li&gt;PHP  &lt;li&gt;PVCS Team Tracker  &lt;li&gt;Python &lt;li&gt;Ruby &lt;li&gt;Scripting  &lt;li&gt;UML  &lt;li&gt;Unix/Linux  &lt;li&gt;VB  &lt;li&gt;Web App  &lt;li&gt;XML  &lt;li&gt;XSL&lt;/li&gt;&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1076542910759361186?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1076542910759361186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1076542910759361186'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/skill-keywords-in-it-job-seeking.html' title='Skill keywords in IT job-seeking website'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-5510363114266845296</id><published>2008-10-07T17:07:00.001-07:00</published><updated>2008-10-07T17:08:10.190-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>gcd, binomial number</title><content type='html'>&lt;p&gt;Problem: UVa 530 &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;page=show_problem&amp;amp;problem=471"&gt;Binomial Showdown&lt;/a&gt;&lt;/p&gt; &lt;p&gt;这道题我用了cache + online computation, 一小部分数据先算好，不在表里的现算，在表内的直接查表&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; uLL;&lt;br /&gt;uLL gcd(uLL a, uLL b) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(a % b == 0) &lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; b;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; gcd(b, a%b);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; divbygcd(uLL &amp;amp;a, uLL &amp;amp;b) {&lt;br /&gt;    uLL g = gcd(a,b);&lt;br /&gt;    a /= g;&lt;br /&gt;    b /= g;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;uLL combination(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k) {&lt;br /&gt;    uLL num = 1, den = 1, tomul, todiv, i;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(k &amp;gt; n/2) k = n-k; &lt;span style="color: #008000"&gt;//use smaller k&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(i = k; i; --i) {&lt;br /&gt;        tomul = n-k+i;&lt;br /&gt;        todiv = i;&lt;br /&gt;        divbygcd(tomul, todiv);&lt;br /&gt;        divbygcd(num, todiv);&lt;br /&gt;        divbygcd(tomul, den);&lt;br /&gt;        num *= tomul;&lt;br /&gt;        den *= todiv;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; num / den;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-5510363114266845296?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5510363114266845296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/5510363114266845296'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/gcd-binomial-number.html' title='gcd, binomial number'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-3922456777606144124</id><published>2008-10-07T12:36:00.000-07:00</published><updated>2008-10-07T14:16:32.552-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>Prime Numbers</title><content type='html'>&lt;pre&gt;&lt;strong&gt;&lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=primeNumbers"&gt;Sieve of Eratosthenes&lt;/a&gt;:&lt;/strong&gt; &lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;cmath&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; MAX = 1000000;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; SQRT_MAX = (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)sqrt(MAX);&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;short&lt;/span&gt; primes[MAX];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; gen_primes() &lt;br /&gt;{ &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i=0;i&amp;lt;MAX;i++) &lt;br /&gt;    primes[i] = 1; &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i=2; i&amp;lt;= SQRT_MAX;i++) &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (primes[i]) &lt;br /&gt;      &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j=i;j*i&amp;lt;MAX;j++) &lt;br /&gt;        primes[i*j] = 0; &lt;br /&gt;} &lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;or use our bitvector to store primes[]:&lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;Problem: UVa 543: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;page=show_problem&amp;amp;problem=484"&gt;Goldbach's Conjecture&lt;/a&gt;&lt;/pre&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; MAX = 1000001;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; SQRT_MAX = 1000;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; SHIFT = 5;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; MASK = (1&amp;lt;&amp;lt;SHIFT)-1;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SET(&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i) {&lt;br /&gt;	a[i&amp;gt;&amp;gt;SHIFT] |= (1 &amp;lt;&amp;lt; (i &amp;amp; MASK));&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; CLEAR(&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i) {&lt;br /&gt;	a[i&amp;gt;&amp;gt;SHIFT] &amp;amp;= ~(1 &amp;lt;&amp;lt; (i &amp;amp; MASK));&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; TEST(&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i) {&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; a[i&amp;gt;&amp;gt; SHIFT] &amp;amp; (1 &amp;lt;&amp;lt; (i &amp;amp; MASK));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N = MAX/(&lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)&amp;lt;&amp;lt;3);&lt;br /&gt;&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; primes[N+1];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; gen_primes() &lt;br /&gt;{ &lt;br /&gt;    memset(primes, 0xAAAAAAAA, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(primes));&lt;br /&gt;    SET(primes, 2);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 3; i &amp;lt;= SQRT_MAX; ++ i) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (TEST(primes, i))  {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = i; j * i &amp;lt; MAX; ++ j)  {&lt;br /&gt;                CLEAR(primes, i * j);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;    gen_primes();&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;n) &amp;amp;&amp;amp; n) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 2, pos = 0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p = n-i;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(TEST(primes,i) &amp;amp;&amp;amp; TEST(primes, p)) {             &lt;br /&gt;                printf("&lt;span style="color: #8b0000"&gt;%d = %d + %d\n&lt;/span&gt;", n, i, p);&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(!TEST(primes,++i)) {};&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-3922456777606144124?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3922456777606144124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3922456777606144124'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/prime-numbers.html' title='Prime Numbers'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2438761063540534793</id><published>2008-10-04T14:15:00.001-07:00</published><updated>2008-10-04T14:52:09.820-07:00</updated><title type='text'>Flickr Photostream</title><content type='html'>&lt;center&gt;&lt;p&gt;&lt;script type="text/javascript" src="http://www.flickr.com/badge_code_v2.gne?count=4&amp;amp;display=random&amp;amp;size=s&amp;amp;layout=h&amp;amp;source=user&amp;amp;user=86139015@N00"&gt;&lt;/script&gt;&lt;br /&gt; &lt;script type="text/javascript" src="http://www.flickr.com/badge_code_v2.gne?count=4&amp;amp;display=random&amp;amp;size=s&amp;amp;layout=h&amp;amp;source=user&amp;amp;user=86139015@N00"&gt;&lt;/script&gt;&lt;br /&gt; &lt;script type="text/javascript" src="http://www.flickr.com/badge_code_v2.gne?count=4&amp;amp;display=random&amp;amp;size=s&amp;amp;layout=h&amp;amp;source=user&amp;amp;user=86139015@N00"&gt;&lt;/script&gt;&lt;br /&gt; &lt;script type="text/javascript" src="http://www.flickr.com/badge_code_v2.gne?count=4&amp;amp;display=random&amp;amp;size=s&amp;amp;layout=h&amp;amp;source=user&amp;amp;user=86139015@N00"&gt;&lt;/script&gt;&lt;/p&gt;&lt;/center&gt;   BTW, get your flickr user id &lt;a href="http://idgettr.com/"&gt;here&lt;/a&gt;.  Also check    &lt;a href="http://flickrslidr.com/index.php"&gt;this&lt;/a&gt;.  &lt;center&gt;&lt;object type="text/html" data="http://www.flickr.com/slideShow/index.gne?group_id=&amp;user_id=86139015@N00&amp;set_id=&amp;text=" width="332" height="332"&gt;&lt;/object&gt;&lt;br/&gt;&lt;small&gt;Created with &lt;a href="http://www.admarket.se" title="Admarket.se"&gt;Admarket's&lt;/a&gt; &lt;a href="http://flickrslidr.com" title="flickrSLiDR"&gt;flickrSLiDR&lt;/a&gt;.&lt;/small&gt;&lt;/center&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2438761063540534793?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2438761063540534793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2438761063540534793'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/blog-post.html' title='Flickr Photostream'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-8001017159340389780</id><published>2008-10-02T08:16:00.001-07:00</published><updated>2008-10-02T19:56:15.535-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data structure'/><title type='text'>Trie</title><content type='html'>&lt;p&gt;topCoder article: &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=usingTries"&gt;Using Tries&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This data structure is used to index and search strings inside a text. Trie allows us to find words that have a single character different, a prefix in common, a character missing, etc. Running time: O(L), where L is the length of a single word.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/greeness/SOTlsNxIcGI/AAAAAAAAB1Y/7khROwSfAr0/image%5B5%5D.png"&gt;&lt;img style="margin: 5px 40px 0px 5px" height="240" alt="image" src="http://lh3.ggpht.com/greeness/SOTlsdmFWWI/AAAAAAAAB1c/GLHy4vhlEOI/image_thumb%5B3%5D.png" width="238" align="left"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The left figure is an example from topcoder article. It shows a trie with the words "tree", "trie", "algo", "assoc", "all", and "also". &lt;/p&gt; &lt;ul&gt; &lt;li&gt;The trie is a tree where each vertex represents a single word or a prefix.  &lt;li&gt;The root represents an empty string (""), the vertexes that are direct sons of the root represent prefixes of length 1, the vertexes that are 2 edges of distance from the root represent prefixes of length 2, the vertexes that are 3 edges of distance from the root represent prefixes of length 3 and so on. In other words, a vertex that are &lt;em&gt;k&lt;/em&gt; edges of distance of the root have an associated prefix of length &lt;em&gt;k&lt;/em&gt;.  &lt;li&gt;Let &lt;strong&gt;v&lt;/strong&gt; and &lt;strong&gt;w&lt;/strong&gt; be two vertexes of the trie, and assume that &lt;strong&gt;v&lt;/strong&gt; is a direct father of &lt;strong&gt;w&lt;/strong&gt;, then &lt;strong&gt;v&lt;/strong&gt; must have an associated prefix of &lt;strong&gt;w&lt;/strong&gt;. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;My C++ Code:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// Interval node data structure&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Node {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m_n = 26;  &lt;span style="color: #008000"&gt;// maximum number of kids&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;:   &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; m_data;         &lt;span style="color: #008000"&gt;// data stored at current node&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m_prefixes;   &lt;span style="color: #008000"&gt;// how many words have the prefix of the vertex&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m_words;      &lt;span style="color: #008000"&gt;// the number of words that match with a given string&lt;/span&gt;&lt;br /&gt;    Node* m_kids[m_n];  &lt;span style="color: #008000"&gt;// pointers to all its kids&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: #008000"&gt;// create an empty node&lt;/span&gt;&lt;br /&gt;    Node(): m_data(' '), m_prefixes(0), m_words(0) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_n; ++i)&lt;br /&gt;            m_kids[i] = NULL;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// create a node to store data v&lt;/span&gt;&lt;br /&gt;    Node(&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; v): m_data(v), m_prefixes(0), m_words(0) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_n; ++i)&lt;br /&gt;            m_kids[i] = NULL;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// copy constructor, recursively copy nodes from p&lt;/span&gt;&lt;br /&gt;    Node(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; Node&amp;amp; p) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_data = p.m_data;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_prefixes = p.m_prefixes;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_words = p.m_words;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_n; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p.m_kids[i] == NULL) {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_kids[i] = NULL;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_kids[i] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Node(*p.m_kids[i]);&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// print substree rooted at p&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Print(Node* p, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix) &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nkids = 0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_n; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p-&amp;gt;m_kids[i] == NULL) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;            Print(p-&amp;gt;m_kids[i], prefix + p-&amp;gt;m_data);&lt;br /&gt;            nkids++;&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(nkids == 0) {&lt;br /&gt;            std::cout &amp;lt;&amp;lt; prefix+p-&amp;gt;m_data &amp;lt;&amp;lt; std::endl;&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// add words rooted at p&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddWord(Node* p, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; word) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(word.empty())&lt;br /&gt;            p-&amp;gt;m_words ++;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {&lt;br /&gt;            p-&amp;gt;m_prefixes ++;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = word[0]-'a';&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p-&amp;gt;m_kids[k] == NULL) &lt;br /&gt;                p-&amp;gt;m_kids[k] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Node(word[0]);&lt;br /&gt;            AddWord(p-&amp;gt;m_kids[k], word.substr(1));&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CountWords(Node *p, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; word) &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;{&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = word[0]-'a';&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(word.empty())&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; p-&amp;gt;m_words;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p-&amp;gt;m_kids[k] == NULL)&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; CountWords(p-&amp;gt;m_kids[k], word.substr(1));&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CountPrefixes(Node *p, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix) &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;{&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = prefix[0]-'a';&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(prefix.empty())&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; p-&amp;gt;m_prefixes;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(p-&amp;gt;m_kids[k] == NULL)&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; CountWords(p-&amp;gt;m_kids[k], prefix.substr(1));&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// recursively delete node tree&lt;/span&gt;&lt;br /&gt;    ~Node() {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_n; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_kids[i] == NULL) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_kids[i];&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #008000"&gt;// Trie data structure&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Trie {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;    Trie() {m_root = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Node(' ');};&lt;br /&gt;    Trie(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; Trie &amp;amp;t) { m_root = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Node(*t.m_root);}&lt;br /&gt;    ~Trie() {&lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; m_root;};&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddWord(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; word) { m_root-&amp;gt;AddWord(m_root, word); }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CountWords(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; word) { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_root-&amp;gt;CountWords(m_root, word);}&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CountPrefixes(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix) {&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_root-&amp;gt;CountPrefixes(m_root, prefix);}&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Print() {m_root-&amp;gt;Print(m_root, std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;&lt;/span&gt;"));}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;: &lt;br /&gt;    &lt;span style="color: #008000"&gt;// root node&lt;/span&gt;&lt;br /&gt;    Node* m_root;&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;    Trie* t = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Trie();&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;tree&lt;/span&gt;")); &lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;trie&lt;/span&gt;")); &lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;trie&lt;/span&gt;")); &lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;trie&lt;/span&gt;")); &lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;trie&lt;/span&gt;"));&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;trieg&lt;/span&gt;"));&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;algo&lt;/span&gt;"));&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;algo&lt;/span&gt;"));&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;assoc&lt;/span&gt;"));&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;all&lt;/span&gt;"));&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;allall&lt;/span&gt;"));&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;allus&lt;/span&gt;"));&lt;br /&gt;    t-&amp;gt;AddWord(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;also&lt;/span&gt;"));&lt;br /&gt;&lt;br /&gt;    t-&amp;gt;Print();&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", t-&amp;gt;CountPrefixes(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;trie&lt;/span&gt;")));  &lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", t-&amp;gt;CountPrefixes(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;trieg&lt;/span&gt;")));&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", t-&amp;gt;CountWords(std::&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;("&lt;span style="color: #8b0000"&gt;trie&lt;/span&gt;")));&lt;br /&gt;    &lt;br /&gt;    Trie r(*t);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; t;&lt;br /&gt;    r.Print();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;output: &lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt; algo&lt;br&gt; allall&lt;br&gt; allus&lt;br&gt; also&lt;br&gt; assoc&lt;br&gt; tree&lt;br&gt; trieg&lt;br&gt;4&lt;br&gt;1&lt;br&gt;4&lt;br&gt; algo&lt;br&gt; allall&lt;br&gt; allus&lt;br&gt; also&lt;br&gt; assoc&lt;br&gt; tree&lt;br&gt; trieg&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-8001017159340389780?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8001017159340389780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8001017159340389780'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/10/trie.html' title='Trie'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/greeness/SOTlsdmFWWI/AAAAAAAAB1c/GLHy4vhlEOI/s72-c/image_thumb%5B3%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-3822201100126301436</id><published>2008-09-30T19:40:00.001-07:00</published><updated>2008-09-30T21:21:49.138-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><title type='text'>MST (minimum spanning tree)</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;Kruskal's algorithm &lt;/b&gt;&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// G: graph&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// w: weight&lt;/span&gt;&lt;br /&gt;MST-Kruskal(G, w)&lt;br /&gt;  A = empty set&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; each vertex v in V[G]&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;do&lt;/span&gt; Make-Set(v)&lt;br /&gt;  sort the edges of E into nondecreasing order by weight w&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; each edge (u,v) in E, taken in nondecreasing order by weight w&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;do&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; Find-Set(u) != Find-Set(v)&lt;br /&gt;          then A = A &lt;span style="color: #0000ff"&gt;union&lt;/span&gt; {(u,v)}&lt;br /&gt;               Union(u,v)&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; A &lt;span style="color: #008000"&gt;// MST&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Animation: &lt;/strong&gt;&lt;b&gt;&lt;i&gt;&lt;a href="Kruskal Algorithm"&gt;Kruskal Algorithm&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Problem: topcoder &lt;b&gt;&lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=7921&amp;amp;rd=10765" name="7921"&gt;RoadReconstruction&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm356"&gt;Editorial&lt;/a&gt;:&amp;nbsp; &lt;/strong&gt;This problem can be solved by modification of standard &lt;a href="http://en.wikipedia.org/wiki/Kruskal_algorithm"&gt;Kruskal algorithm&lt;/a&gt; of finding MST (minimal spanning tree) in undirected graph. Cities will be the vertice of that graph, and roads will be its edges. Each damaged road will provide the corresponding edge the weight that equals the cost of the reconstruction. Other (non-damaged) roads will have weight 0. &lt;br&gt;Now, let's sort all the edges in ascending order of their weights, and in the case of a tie - in the lexicographical order of their identifiers. &lt;br&gt;The Kruskal algorithm gives us the minimal spanning tree. Finally, to obtain the answer to the problem let's remove all edges that don't need to be reconstructed from MST. Don't forget to sort the remaining identifiers in the lexicographical order! &lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;下面是&lt;a href="http://www.topcoder.com/tc?module=MemberProfile&amp;amp;cr=21185521&amp;amp;tab=alg"&gt;Zhomart&lt;/a&gt;'s &lt;a href="http://www.topcoder.com/stat?c=problem_solution&amp;amp;rm=265407&amp;amp;rd=10765&amp;amp;pm=7921&amp;amp;cr=21185521"&gt;solution&lt;/a&gt;, 注意他对i/o的处理 (sscanf)，customized sort, &lt;/p&gt;&lt;pre&gt;#include&amp;lt;iostream&amp;gt;&lt;br /&gt;#include&amp;lt;cstdio&amp;gt;&lt;br /&gt;#include&amp;lt;map&amp;gt;&lt;br /&gt;#include&amp;lt;cmath&amp;gt;&lt;br /&gt;#include&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;&lt;br /&gt;#include&amp;lt;vector&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; ROAD {&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; id1,id2,cost;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; ID[51];&lt;br /&gt;}tr;&lt;br /&gt;map&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; names;&lt;br /&gt;vector&amp;lt;ROAD&amp;gt; ed;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; ID[51],STR1[51],STR2[51];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N,col[51];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; compare(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; ROAD &amp;amp;r1,&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; ROAD &amp;amp;r2) {&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( r1.cost!=r2.cost ) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; r1.cost&amp;lt;r2.cost;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;(r1.ID)&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;(r2.ID);&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; RoadReconstruction {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; selectReconstruction(vector&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; ss) {&lt;br /&gt;     N = 0;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i=0; i&amp;lt;ss.size(); ++i) {&lt;br /&gt;        ss[i]+=' ';&lt;br /&gt;        tr.cost=0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( sscanf(ss[i].c_str(),"&lt;span style="color: #8b0000"&gt;%s %s %s %d&lt;/span&gt;",tr.ID,STR1,STR2,&amp;amp;tr.cost)==3 ) tr.cost=0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( names[STR1]==0 ) names[STR1] = ++N;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( names[STR2]==0 ) names[STR2] = ++N;&lt;br /&gt;        tr.id1 = names[STR1];&lt;br /&gt;        tr.id2 = names[STR2];&lt;br /&gt;        ed.push_back(tr);&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i=1; i&amp;lt;=N; ++i)&lt;br /&gt;        col[i] = i;&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; M = N;&lt;br /&gt;     sort(ed.begin(),ed.end(),compare);&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; res="&lt;span style="color: #8b0000"&gt;&lt;/span&gt;";&lt;br /&gt;     vector&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; rr;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i=0; i&amp;lt;ed.size(); ++i)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( col[ ed[i].id1 ] != col[ ed[i].id2 ] ) {&lt;br /&gt;           &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ccol = col[ed[i].id1],new_col = col[ed[i].id2];&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;           //after union, update union id&lt;/span&gt;           &lt;br /&gt;           &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j=1; j&amp;lt;=N; ++j)&lt;br /&gt;              &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( col[j]==ccol ) col[j] = new_col;&lt;br /&gt;&lt;span style="color: #008000"&gt;           // if it is a damaged road&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( ed[i].cost&amp;gt;0 )&lt;br /&gt;              rr.push_back(ed[i].ID);&lt;br /&gt;           M--; &lt;span style="color: #008000"&gt;// total set number --, it is supposed to be 1 set left after MST is done&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;     sort(rr.begin(),rr.end());&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i=0; i&amp;lt;rr.size(); ++i) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( i&amp;gt;0 ) res+="&lt;span style="color: #8b0000"&gt; &lt;/span&gt;";&lt;br /&gt;        res+=rr[i];&lt;br /&gt;     }&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;( M!=1 ) res = "&lt;span style="color: #8b0000"&gt;IMPOSSIBLE&lt;/span&gt;";&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; res;&lt;br /&gt;  }&lt;br /&gt;};&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Prim's algorithm&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-3822201100126301436?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3822201100126301436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3822201100126301436'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/mst-minimum-spanning-tree.html' title='MST (minimum spanning tree)'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-2146204852680680103</id><published>2008-09-30T14:37:00.001-07:00</published><updated>2008-09-30T19:39:57.352-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='disjoint set'/><title type='text'>Union Find</title><content type='html'>&lt;p&gt;By &lt;a href="http://en.wikipedia.org/wiki/Disjoint-set_data_structure"&gt;wiki&lt;/a&gt;: A &lt;b&gt;union-find algorithm&lt;/b&gt; is an algorithm that performs two useful operations on such a data structure:  &lt;ul&gt; &lt;li&gt;&lt;i&gt;Find&lt;/i&gt;: Determine which set a particular element is in. Also useful for determining if two elements are in the same set.  &lt;li&gt;&lt;i&gt;Union&lt;/i&gt;: Combine or merge two sets into a single set. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=disjointDataStructure"&gt;topCoder article&lt;/a&gt; on Union Find&lt;/p&gt; &lt;h4&gt;Applications&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;Disjoint-set data structures model the &lt;a href="http://en.wikipedia.org/wiki/Partition_of_a_set"&gt;partitioning of a set&lt;/a&gt;, for example to keep track of the &lt;a href="http://en.wikipedia.org/wiki/Connected_component_%28graph_theory%29"&gt;components of a graph&lt;/a&gt; of an &lt;a href="http://en.wikipedia.org/wiki/Undirected_graph"&gt;undirected graph&lt;/a&gt;. This model can then be used to determine whether two vertices belong to the same component, or whether adding an edge between them would result in a cycle.  &lt;li&gt;This data structure is used by the &lt;a href="http://en.wikipedia.org/wiki/Boost_Graph_Library"&gt;Boost Graph Library&lt;/a&gt; to implement its &lt;a href="http://www.boost.org/libs/graph/doc/incremental_components.html"&gt;Incremental Connected Components&lt;/a&gt; functionality.  &lt;li&gt;It is also used for implementing &lt;a href="http://en.wikipedia.org/wiki/Kruskal%27s_algorithm"&gt;Kruskal's algorithm&lt;/a&gt; to find the &lt;a href="http://en.wikipedia.org/wiki/Minimum_spanning_tree"&gt;minimum spanning tree&lt;/a&gt; of a graph.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Visualization&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.cs.unm.edu/~rlpm/499/uf.html"&gt;A Graphical Union-Find Implementation&lt;/a&gt;  &lt;li&gt;&lt;a href="http://research.cs.vt.edu/algoviz/UF/"&gt;Union/Find Algorithm Visualization&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;a very clear &lt;a href="http://www.emilstefanov.net/Programming/DisjointSets.aspx"&gt;C++ implementation by Emil Stefanov&lt;/a&gt; &lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// Disjoint Set Data Structure&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// Author: Emil Stefanov&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// Date: 03/28/06&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// Implementaton is as described in http://en.wikipedia.org/wiki/Disjoint-set_data_structure&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;cassert&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DisjointSets&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;    // Create an empty DisjointSets data structure&lt;/span&gt;&lt;br /&gt;    DisjointSets(){&lt;br /&gt;	    m_numElements = 0;&lt;br /&gt;	    m_numSets = 0;&lt;br /&gt;    };&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Create a DisjointSets data structure with a specified number of elements (with element id's from 0 to count-1)&lt;/span&gt;&lt;br /&gt;    DisjointSets(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; count){&lt;br /&gt;	    m_numElements = 0;&lt;br /&gt;	    m_numSets = 0;&lt;br /&gt;	    AddElements(count);&lt;br /&gt;    };&lt;br /&gt;    &lt;span style="color: #008000"&gt;// Copy constructor&lt;/span&gt;&lt;br /&gt;    DisjointSets(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; DisjointSets &amp;amp; s){&lt;br /&gt;	    &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_numElements = s.m_numElements;&lt;br /&gt;	    &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;-&amp;gt;m_numSets = s.m_numSets;&lt;br /&gt;&lt;br /&gt;	    &lt;span style="color: #008000"&gt;// Copy nodes&lt;/span&gt;&lt;br /&gt;	    m_nodes.resize(m_numElements);&lt;br /&gt;	    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_numElements; ++i)&lt;br /&gt;		    m_nodes[i] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Node(*s.m_nodes[i]);&lt;br /&gt;&lt;br /&gt;	    &lt;span style="color: #008000"&gt;// Update parent pointers to point to newly created nodes rather than the old ones&lt;/span&gt;&lt;br /&gt;	    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_numElements; ++i)&lt;br /&gt;		    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(m_nodes[i]-&amp;gt;parent != NULL)&lt;br /&gt;			    m_nodes[i]-&amp;gt;parent = m_nodes[s.m_nodes[i]-&amp;gt;parent-&amp;gt;index];&lt;br /&gt;    };&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Destructor&lt;/span&gt;&lt;br /&gt;    ~DisjointSets(){&lt;br /&gt;	    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_numElements; ++i)&lt;br /&gt;		    &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; m_nodes[i];&lt;br /&gt;	    m_nodes.clear();&lt;br /&gt;	    m_numElements = 0;&lt;br /&gt;	    m_numSets = 0;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Find the set identifier that an element currently belongs to.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Note: some internal data is modified for optimization even though this method is consant.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;int&lt;/span&gt; FindSet(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; element) &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Combine two sets into one. All elements in those two sets will share the same set id that can be gotten using FindSet.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;void&lt;/span&gt; Union(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; setId1, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; setId2);&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Add a specified number of elements to the DisjointSets data structure. The element id's of the new elements are numbered&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// consequitively starting with the first never-before-used elementId.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;void&lt;/span&gt; AddElements(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; numToAdd){&lt;br /&gt;	    assert(numToAdd &amp;gt;= 0);&lt;br /&gt;	    &lt;span style="color: #008000"&gt;// insert and initialize the specified number of element nodes to the end of the `m_nodes` array&lt;/span&gt;&lt;br /&gt;	    m_nodes.insert(m_nodes.end(), numToAdd, (Node*)NULL);&lt;br /&gt;	    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = m_numElements; i &amp;lt; m_numElements + numToAdd; ++i)&lt;br /&gt;	    {&lt;br /&gt;		    m_nodes[i] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Node();&lt;br /&gt;		    m_nodes[i]-&amp;gt;parent = NULL;&lt;br /&gt;		    m_nodes[i]-&amp;gt;index = i;&lt;br /&gt;		    m_nodes[i]-&amp;gt;rank = 0;&lt;br /&gt;	    }&lt;br /&gt;&lt;br /&gt;	    &lt;span style="color: #008000"&gt;// update element and set counts&lt;/span&gt;&lt;br /&gt;	    m_numElements += numToAdd;&lt;br /&gt;	    m_numSets += numToAdd;&lt;br /&gt;    };&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Returns the number of elements currently in the DisjointSets data structure.&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; NumElements() &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; {&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_numElements;};&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Returns the number of sets currently in the DisjointSets data structure.&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; NumSets() &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; {&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_numSets;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;:&lt;br /&gt;&lt;span style="color: #008000"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;// Internal Node data structure used for representing an element&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;struct&lt;/span&gt; Node&lt;br /&gt;    {&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; rank; &lt;span style="color: #008000"&gt;// This roughly represent the max height of the node in its subtree&lt;/span&gt;&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; index; &lt;span style="color: #008000"&gt;// The index of the element the node represents&lt;/span&gt;&lt;br /&gt;	Node* parent; &lt;span style="color: #008000"&gt;// The parent node of the node&lt;/span&gt;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;int&lt;/span&gt; m_numElements; &lt;span style="color: #008000"&gt;// the number of elements currently in the DisjointSets data structure.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;    &lt;/font&gt;int&lt;/span&gt; m_numSets; &lt;span style="color: #008000"&gt;// the number of sets currently in the DisjointSets data structure.&lt;/span&gt;&lt;br /&gt;    std::vector&amp;lt;Node*&amp;gt; m_nodes; &lt;span style="color: #008000"&gt;// the list of nodes representing the elements&lt;/span&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// Note: some internal data is modified for optimization even though this method is consant.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// path compression&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; DisjointSets::FindSet(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; elementId) &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;	assert(elementId &amp;lt; m_numElements);&lt;br /&gt;	Node* curNode;&lt;br /&gt;&lt;br /&gt;	&lt;span style="color: #008000"&gt;// Find the root element that represents the set which `elementId` belongs to&lt;/span&gt;&lt;br /&gt;	curNode = m_nodes[elementId];&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(curNode-&amp;gt;parent != NULL)&lt;br /&gt;		curNode = curNode-&amp;gt;parent;&lt;br /&gt;	Node* root = curNode;&lt;br /&gt;&lt;br /&gt;	&lt;span style="color: #008000"&gt;// Walk to the root, updating the parents of `elementId`. Make those elements the direct&lt;/span&gt;&lt;br /&gt;	&lt;span style="color: #008000"&gt;// children of `root`. This optimizes the tree for future FindSet invokations.&lt;/span&gt;&lt;br /&gt;	curNode = m_nodes[elementId];&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(curNode != root)&lt;br /&gt;	{&lt;br /&gt;		Node* next = curNode-&amp;gt;parent;&lt;br /&gt;		curNode-&amp;gt;parent = root;&lt;br /&gt;		curNode = next;&lt;br /&gt;	}&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; root-&amp;gt;index;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// union by rank&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DisjointSets::Union(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; setId1, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; setId2)&lt;br /&gt;{&lt;br /&gt;	assert(setId1 &amp;lt; m_numElements);&lt;br /&gt;	assert(setId2 &amp;lt; m_numElements);&lt;br /&gt;	assert(setId1 != setId2);&lt;br /&gt;&lt;br /&gt;	Node* set1 = m_nodes[setId1];&lt;br /&gt;	Node* set2 = m_nodes[setId2];&lt;br /&gt;&lt;br /&gt;	&lt;span style="color: #008000"&gt;// Determine which node representing a set has a higher rank. The node with the higher rank is&lt;/span&gt;&lt;br /&gt;	&lt;span style="color: #008000"&gt;// likely to have a bigger subtree so in order to better balance the tree representing the&lt;/span&gt;&lt;br /&gt;	&lt;span style="color: #008000"&gt;// union, the node with the higher rank is made the parent of the one with the lower rank and&lt;/span&gt;&lt;br /&gt;	&lt;span style="color: #008000"&gt;// not the other way around.&lt;/span&gt;&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(set1-&amp;gt;rank &amp;gt; set2-&amp;gt;rank)&lt;br /&gt;		set2-&amp;gt;parent = set1;&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(set1-&amp;gt;rank &amp;lt; set2-&amp;gt;rank)&lt;br /&gt;		set1-&amp;gt;parent = set2;&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #008000"&gt;// set1-&amp;gt;rank == set2-&amp;gt;rank&lt;/span&gt;&lt;br /&gt;	{&lt;br /&gt;		set2-&amp;gt;parent = set1;&lt;br /&gt;		++set1-&amp;gt;rank; &lt;span style="color: #008000"&gt;// update rank&lt;/span&gt;&lt;br /&gt;	}&lt;br /&gt;	&lt;span style="color: #008000"&gt;// Since two sets have fused into one, there is now one less set so update the set count.&lt;/span&gt;&lt;br /&gt;	--m_numSets;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; printElementSets(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; DisjointSets &amp;amp; s)&lt;br /&gt;{&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; s.NumElements(); ++i)&lt;br /&gt;		cout &amp;lt;&amp;lt; s.FindSet(i) &amp;lt;&amp;lt; "&lt;span style="color: #8b0000"&gt;  &lt;/span&gt;";&lt;br /&gt;	cout &amp;lt;&amp;lt; endl;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main()&lt;br /&gt;{&lt;br /&gt;	DisjointSets s(10);&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.Union(s.FindSet(5),s.FindSet(3));&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.Union(s.FindSet(1),s.FindSet(3));&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.Union(s.FindSet(6),s.FindSet(7));&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.Union(s.FindSet(8),s.FindSet(9));&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.Union(s.FindSet(6),s.FindSet(9));&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.AddElements(3);&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.Union(s.FindSet(11),s.FindSet(12));&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.Union(s.FindSet(9),s.FindSet(10));&lt;br /&gt;	printElementSets(s);&lt;br /&gt;	s.Union(s.FindSet(7),s.FindSet(11));&lt;br /&gt;	printElementSets(s);&lt;br /&gt;&lt;br /&gt;	system("&lt;span style="color: #8b0000"&gt;pause&lt;/span&gt;");&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;/pre&gt;&lt;pre&gt;output:&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;0&amp;nbsp; 1&amp;nbsp; 2&amp;nbsp; 3&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 7&amp;nbsp; 8&amp;nbsp; 9&lt;br&gt;0&amp;nbsp; 1&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 7&amp;nbsp; 8&amp;nbsp; 9&lt;br&gt;0&amp;nbsp; 5&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 7&amp;nbsp; 8&amp;nbsp; 9&lt;br&gt;0&amp;nbsp; 5&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 8&amp;nbsp; 9&lt;br&gt;0&amp;nbsp; 5&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 8&amp;nbsp; 8&lt;br&gt;0&amp;nbsp; 5&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&lt;br&gt;0&amp;nbsp; 5&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 10&amp;nbsp; 11&amp;nbsp; 12&lt;br&gt;0&amp;nbsp; 5&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 10&amp;nbsp; 11&amp;nbsp; 11&lt;br&gt;0&amp;nbsp; 5&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 11&amp;nbsp; 11&lt;br&gt;0&amp;nbsp; 5&amp;nbsp; 2&amp;nbsp; 5&amp;nbsp; 4&amp;nbsp; 5&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&amp;nbsp; 6&lt;br&gt;Press any key to continue . . .&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Problem: topCoder &lt;b&gt;&lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=2998&amp;amp;rd=5857" name="2998"&gt;grafixMask&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm211"&gt;Editorial&lt;/a&gt; suggest using a floodFill with BFS (DFS might have stack overflow problem)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;We can also use Union-Find to solve this problem.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-2146204852680680103?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2146204852680680103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/2146204852680680103'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/union-find.html' title='Union Find'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-3721702397813122240</id><published>2008-09-29T18:21:00.001-07:00</published><updated>2008-10-14T04:53:43.977-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><title type='text'>bit operation</title><content type='html'>&lt;a href="http://www.andrewwinter.com/programming/bitwise/"&gt;http://www.andrewwinter.com/programming/bitwise/&lt;/a&gt;&lt;br /&gt;&lt;p&gt;topCoder: &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=bitManipulation"&gt;A bit of fun: fun with bits&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;dl&gt; &lt;dt&gt;&lt;/dt&gt;&lt;/dl&gt;&lt;tt&gt; &lt;p&gt; &lt;dl&gt; &lt;dt&gt;Set union  &lt;dd&gt;&lt;tt&gt;A | B&lt;/tt&gt;  &lt;dt&gt;Set intersection  &lt;dd&gt;&lt;tt&gt;A &amp;amp; B&lt;/tt&gt;  &lt;dt&gt;Set subtraction  &lt;dd&gt;&lt;tt&gt;A &amp;amp; ~B&lt;/tt&gt;  &lt;dt&gt;Set negation  &lt;dd&gt;&lt;tt&gt;ALL_BITS ^ A&lt;/tt&gt;  &lt;dt&gt;Set bit  &lt;dd&gt;&lt;tt&gt;A |= 1 &amp;lt;&amp;lt; bit&lt;/tt&gt;  &lt;dt&gt;Clear bit  &lt;dd&gt;&lt;tt&gt;A &amp;amp;= ~(1 &amp;lt;&amp;lt; bit)&lt;/tt&gt;&lt;/dd&gt;&lt;/dl&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;tt&gt;Negate bit&lt;/tt&gt;&lt;/p&gt; &lt;p&gt;&lt;tt&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/tt&gt;&lt;tt&gt;A ^= (1 &amp;lt;&amp;lt; bit)&lt;/tt&gt;&lt;/p&gt; &lt;p&gt; &lt;dl&gt; &lt;dt&gt;Test bit  &lt;dd&gt;&lt;tt&gt;(A &amp;amp; 1 &amp;lt;&amp;lt; bit) != 0&lt;/tt&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/tt&gt;&lt;/blockquote&gt; &lt;p&gt;Programming Pearls: bitvector functions&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; SHIFT = 5;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; MASK = (1&amp;lt;&amp;lt;SHIFT)-1;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SET(&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i) {&lt;br /&gt; a[i&amp;gt;&amp;gt;SHIFT] |= (1 &amp;lt;&amp;lt; (i &amp;amp; MASK));&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; CLEAR(&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i) {&lt;br /&gt; a[i&amp;gt;&amp;gt;SHIFT] &amp;amp;= ~(1 &amp;lt;&amp;lt; (i &amp;amp; MASK));&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; TEST(&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i) {&lt;br /&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; a[i&amp;gt;&amp;gt; SHIFT] &amp;amp; (1 &amp;lt;&amp;lt; (i &amp;amp; MASK));&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a[1 + N/(&lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)&amp;lt;&amp;lt;3)];&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;上一贴BFS中用的visited最多支持到 2^27, int visited[2^27], 要用512M内存 (再多vc compilier Error C2148: total size of array must not exceed 0x7fffffff bytes --- 2GB) 。用上面这个bitvector数组可以只用 2^22 int, 16M memory，好很多了。相应改动非常少：&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;  int&lt;/span&gt; BFS( ... ) {&lt;br /&gt;    &lt;span style="color: #008000"&gt;// ...&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N = 1 &amp;lt;&amp;lt; (totalslots-1); &lt;span style="color: #008000"&gt;// totalslots+4-5&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; *v = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;[N+1];&lt;br /&gt;    memset(v, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)*(N+1));&lt;br /&gt;    queue&amp;lt;State&amp;gt; Q;&lt;br /&gt;    Q.push(State(status, 0, 0)&lt;br /&gt;    SET(v, status); &lt;span style="color: #008000"&gt;//v[status] = 1;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(!Q.empty()) {&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;                &lt;span style="color: #008000"&gt;// ...&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #008000"&gt;// move to the next stump&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ns = (s.status ^ (uid &amp;lt;&amp;lt; totalslots)) | (next &amp;lt;&amp;lt; totalslots);&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(TEST(v, ns) == 0) { &lt;span style="color: #008000"&gt;//if(v[ns] == 0)&lt;/span&gt;&lt;br /&gt;                    SET(v, ns); &lt;span style="color: #008000"&gt;//v[ns] = 1;&lt;/span&gt;&lt;br /&gt;                }&lt;br /&gt;                &lt;span style="color: #008000"&gt;// ...&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;提交完这份用了bitvector array的代码后，在UVa 上显示运行时间0.000s :-)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Problem: UVa 594: &lt;a href="http://acm.uva.es/p/v5/594.html"&gt;One Little, Two Little, Three Little Endians&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;要注意的是，signed int是带着符号位移位的，所以我先把signed int 转成了 unsigned int&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;/*bit operation*/&lt;/span&gt;&lt;br /&gt;#include "&lt;span style="color: #8b0000"&gt;stdio.h&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;short&lt;/span&gt; shift[4] = {24, 16, 8, 0};&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;n) != EOF) {    &lt;br /&gt;        &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; d = 0;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; m = n;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;            d |= (m &amp;amp; 0xff) &amp;lt;&amp;lt; shift[i];&lt;br /&gt;            m = m &amp;gt;&amp;gt; 8; &lt;br /&gt;        }&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt;%ld converts to %ld\n&lt;/span&gt;", n, d);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-3721702397813122240?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3721702397813122240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3721702397813122240'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/bit-operation.html' title='bit operation'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-4098052846354621197</id><published>2008-09-29T16:13:00.000-07:00</published><updated>2008-09-29T16:52:40.595-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><title type='text'>BFS</title><content type='html'>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Breadth-first_search"&gt;Wiki&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;Applications of BFS&lt;/h4&gt; &lt;p&gt;Breadth-first search can be used to solve many problems in graph theory, for example:  &lt;ul&gt; &lt;li&gt;Finding all &lt;a href="http://en.wikipedia.org/wiki/Connected_component_%28graph_theory%29"&gt;connected components&lt;/a&gt; in a &lt;a href="http://en.wikipedia.org/wiki/Graph_%28data_structure%29"&gt;graph&lt;/a&gt;.  &lt;li&gt;Finding all nodes within one connected component  &lt;li&gt;Copying Collection, &lt;a href="http://en.wikipedia.org/wiki/Cheney%27s_algorithm"&gt;Cheney's algorithm&lt;/a&gt;  &lt;li&gt;Finding the &lt;a href="http://en.wikipedia.org/wiki/Shortest_path"&gt;shortest path&lt;/a&gt; between two nodes &lt;i&gt;u&lt;/i&gt; and &lt;i&gt;v&lt;/i&gt; (in an &lt;a href="http://en.wikipedia.org/wiki/Unweighted_graph"&gt;unweighted graph&lt;/a&gt;)  &lt;li&gt;Finding the &lt;a href="http://en.wikipedia.org/wiki/Shortest_path"&gt;shortest path&lt;/a&gt; between two nodes &lt;i&gt;u&lt;/i&gt; and &lt;i&gt;v&lt;/i&gt; (in a &lt;a href="http://en.wikipedia.org/wiki/Weighted_graph"&gt;weighted graph&lt;/a&gt;: see talk page)  &lt;li&gt;Testing a graph for &lt;a href="http://en.wikipedia.org/wiki/Bipartite_graph"&gt;bipartiteness&lt;/a&gt;  &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Cuthill%E2%80%93McKee_algorithm"&gt;(Reverse) Cuthill–McKee&lt;/a&gt; mesh numbering &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;topcoder example: use BFS to check graph connectivity&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;/*&lt;br /&gt;Graph is considered to be stored as adjacent vertices list.&lt;br /&gt;Also we considered graph undirected.&lt;br /&gt; &lt;br /&gt;vvi is vector&amp;lt; vector&amp;lt;int&amp;gt; &amp;gt;&lt;br /&gt;W[v] is the list of vertices adjacent to v&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;&lt;/span&gt;&lt;span style="color: #008000"&gt;tr is the macro to get iterator and try each element&lt;br /&gt;*/&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N; &lt;span style="color: #008000"&gt;// number of vertices&lt;/span&gt;&lt;br /&gt; vvi W; &lt;span style="color: #008000"&gt;// lists of adjacent vertices&lt;/span&gt;   &lt;br /&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; check_graph_connected_bfs() { &lt;br /&gt;      &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; start_vertex = 0; &lt;br /&gt;      vi V(N, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;); &lt;br /&gt;      queue&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; Q; &lt;br /&gt;      Q.push(start_vertex); &lt;br /&gt;      V[start_vertex] = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;; &lt;br /&gt;      &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(!Q.empty()) { &lt;br /&gt;           &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = Q.front(); &lt;br /&gt;           &lt;span style="color: #008000"&gt;// get the tail element from queue&lt;/span&gt;&lt;br /&gt;           Q.pop(); &lt;br /&gt;           tr(W[i], it) { &lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(!V[*it]) { &lt;br /&gt;                     V[*it] = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;; &lt;br /&gt;                     Q.push(*it); &lt;br /&gt;                } &lt;br /&gt;           } &lt;br /&gt;      } &lt;br /&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (find(all(V), 0) == V.end()); &lt;br /&gt; }  &lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;Problem &lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;UVa 11501 - &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;page=show_problem&amp;amp;problem=2496"&gt;Laurel Creek&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;input : &lt;/p&gt;&lt;pre&gt;7 11&lt;br /&gt;....S......&lt;br /&gt;....|......&lt;br /&gt;B---S......&lt;br /&gt;...........&lt;br /&gt;...........&lt;br /&gt;...........&lt;br /&gt;....S.S...E&lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;7 11 : row and column size &lt;br /&gt;&lt;li&gt;B: starting position; &lt;br /&gt;&lt;li&gt;E: end position; &lt;br /&gt;&lt;li&gt;S: intermediate stump; &lt;br /&gt;&lt;li&gt;- or | : connecting logs &lt;br /&gt;&lt;li&gt;.&amp;nbsp; empty (water) &lt;br /&gt;&lt;li&gt;constraints: row and column size &amp;lt;= 15,&amp;nbsp; stumps # &amp;lt;= 15, all logs exist between stumps&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt; 一开始就用了BFS，做起来发现状态太多了。难点就在于怎样记录已经访问过的状态。开始试了一种状态表示，后来证明是错误的。当时用current pos + 该点四周logs的分布情况作为一个单独的状态，其实这是不行的。这种表示方法无法求解出下面这种情况，因为一个状态不仅跟自己所处位置的log相关，还跟其它位置的logs分布也相关。&lt;/p&gt;&lt;pre&gt;....S...S..&lt;br /&gt;........|..&lt;br /&gt;B-----S.|.E&lt;br /&gt;......|.|..&lt;br /&gt;......|.S..&lt;br /&gt;......|....&lt;br /&gt;....S-S....&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;后来先后用了两种方法减少状态空间。利用了这个前提：stumps是固定的，变化的是自己的位置和logs的位置。&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;用一个2D-bitvector (nrow+1)x ncol 记录图中所有log的位置，每个位对应一个'-' 或者 '|', 多出来的一行用来表示当前位置(x* ncol + y)。整个2d-vector作为一个状态存入一个set visited,之后通过查询visited 中是否有该状态存在得知此状态是否访问过。这个版本由于用了stl set 速度比较慢（在测试数据上用的时间是第二种方法的15倍），但可以用于slots比较多的情况。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; bitlog;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; nrow; ++i)&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; ncol; ++j)&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(m[i][j] == '-' || m[i][j] == '|')&lt;br /&gt;          bitlog[i] = bitlog[i] | (1&amp;lt;&amp;lt;j);&lt;br /&gt;bitlog[nrow] = start.first*ncol+start.second;&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;     set&amp;lt;vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; &amp;gt; visited;&lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;在BFS里queue里的元素用了以下类型&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; State{&lt;br /&gt;    ii pos;   &lt;span style="color: #008000"&gt;// current position&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; log;  &lt;span style="color: #008000"&gt;// log length&lt;/span&gt;&lt;br /&gt;    vector&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; maze; &lt;span style="color: #008000"&gt;// graph&lt;/span&gt;&lt;br /&gt;    vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; bitlog;  &lt;span style="color: #008000"&gt;// 2d bitvector&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; step; &lt;span style="color: #008000"&gt;// current step&lt;/span&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Considering the available slots where the log can be picked up or put down, the state space is not that big. Because there are at most 15 stumps with limited row and column size(&amp;lt;= 15) and logs only exist between stumps, the following case is the one that comes with the greatest number of logs. right? &lt;img title="" alt=":roll:" src="http://acm.uva.es/board/images/smilies/icon_rolleyes.gif"&gt;&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;S-S-S-S&lt;br&gt;|.|.|.|&lt;br&gt;S-S-S-S&lt;br&gt;|.|.|.|&lt;br&gt;S-S-S-S&lt;br&gt;|.|.|.|&lt;br&gt;S-S-S-.&lt;br&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;There are less than 24 positions that logs can be put down. Also the current position can be represented with 4 bits (we can only stand on a stump), so the state space can be represented as 4bit + 24bit = 28 bits.&amp;nbsp; 如果有只有7个available slots for logs那么我们的bitvector只用11位就可以了。比如，0110|0110110, 表示现在我们的位置是第6号stump,图中有4个logs，共有7处slots(当然不同长度的log必须放在其相应的slots中，对每个log而言，可能没有7处可用的slots.)&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;/ul&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;queue&amp;gt;&lt;br /&gt;#include &amp;lt;ctime&amp;gt;&lt;br /&gt;#include &amp;lt;map&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; std;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; pair&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; ii;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; State{&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; status;&lt;span style="color: #008000"&gt;// current position + log position&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; log;   &lt;span style="color: #008000"&gt;// log length in hand&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; step;  &lt;span style="color: #008000"&gt;// current step (for outputing shortest step to destination&lt;/span&gt;&lt;br /&gt;    State(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; st, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; l, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; s):status(st), log(l), step(s){}&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// get log width, pos1/pos2 are stumps position&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; length(ii pos1, ii pos2) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(pos1.first == pos2.first) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; abs(pos1.second-pos2.second)-1;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; abs(pos1.first-pos2.first)-1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; BFS(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; start, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; dest, map&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, ii&amp;gt; &amp;amp;stumppos,&lt;br /&gt;        map&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, ii&amp;gt; &amp;amp;slotpos, map&amp;lt;ii,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; &amp;amp;slotlist, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; status) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(start == dest) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// total available slots to put down or pickup logs&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; totalslots = slotlist.size();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// make and clear all visited state&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// a bit vector: highest 4 bit --- current position (stump id#)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// the rest bits: all correspond to an available slot&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;    // use int* instead of vector&amp;lt;int&amp;gt;, the former is a bit faster &lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; *v = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;[(1&amp;lt;&amp;lt; (totalslots + 4))-1];&lt;br /&gt;    memset(v, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)*((1&amp;lt;&amp;lt; (totalslots + 4))-1));&lt;br /&gt;&lt;br /&gt;    queue&amp;lt;State&amp;gt; Q;&lt;br /&gt;    Q.push(State(status, 0, 0));&lt;br /&gt;    v[status] = 1;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(!Q.empty()) {&lt;br /&gt;        State s = Q.front();&lt;br /&gt;        Q.pop();&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;// current position in terms of stump id#&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; uid = s.status &amp;gt;&amp;gt; totalslots;&lt;br /&gt;        &lt;span style="color: #008000"&gt;// current position in terms of (row,col)&lt;/span&gt;&lt;br /&gt;        ii u = stumppos[uid];&lt;br /&gt;&lt;br /&gt;       &lt;span style="color: #008000"&gt;// for each available log&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;// i : slots id&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; totalslots; ++i) &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(s.status &amp;amp; (1&amp;lt;&amp;lt;i)) {&lt;br /&gt;            ii logpair = slotpos[i];&lt;br /&gt;            &lt;span style="color: #008000"&gt;// find a connecting log&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(uid == logpair.first || uid == logpair.second) {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; next = uid == logpair.first? logpair.second: logpair.first;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(next == dest) {&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; [] v; &lt;span style="color: #008000"&gt;// free visited state memory&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; s.step+1;&lt;br /&gt;                }&lt;br /&gt;                &lt;span style="color: #008000"&gt;// move to the next stump&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ns = (s.status ^ (uid &amp;lt;&amp;lt; totalslots)) | (next &amp;lt;&amp;lt; totalslots);&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(v[ns] == 0) {&lt;br /&gt;                    v[ns] = 1;&lt;br /&gt;                    Q.push(State(ns, s.log, s.step+1));&lt;br /&gt;                }              &lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(s.log) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;                &lt;span style="color: #008000"&gt;// pick up a log&lt;/span&gt;&lt;br /&gt;                ns = s.status ^ (1&amp;lt;&amp;lt;i);&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(v[ns] == 0) {&lt;br /&gt;                    v[ns] = 1; &lt;br /&gt;                    &lt;span style="color: #008000"&gt;// log width&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; width = length(stumppos[logpair.first], stumppos[logpair.second]);&lt;br /&gt;                    Q.push(State(ns, width, s.step+1));&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        map&amp;lt;ii,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;::iterator slot_it = slotlist.begin();&lt;br /&gt;        map&amp;lt;ii,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;::iterator slot_end= slotlist.end();&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(; slot_it!= slot_end; ++slot_it) {&lt;br /&gt;            ii slot_pair = slot_it-&amp;gt;first;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = slot_pair.first;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = slot_pair.second; &lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(i != uid &amp;amp;&amp;amp; j != uid) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;            &lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(length(stumppos[i],stumppos[j]) != s.log) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;            ii vv = i == uid ? stumppos[j] : stumppos[i];&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// first, check there is no log between them      &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(s.status &amp;amp; (1&amp;lt;&amp;lt; slot_it-&amp;gt;second)) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; found = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// second, check there are no other logs go through any points between them&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; h1 = u.first == vv.first;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; totalslots; ++i) &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(s.status &amp;amp; (1&amp;lt;&amp;lt;i)) {&lt;br /&gt;                ii logpair = slotpos[i];&lt;br /&gt;                ii pos1 = stumppos[logpair.first];&lt;br /&gt;                ii pos2 = stumppos[logpair.second];&lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;  h2 = (pos1.first == pos2.first);&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(h1 == h2) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(h1 &amp;amp;&amp;amp; pos1.first &amp;lt; u.first &amp;amp;&amp;amp; pos2.first &amp;gt; u.first &amp;amp;&amp;amp;&lt;br /&gt;                    u.second &amp;lt; pos1.second &amp;amp;&amp;amp; vv.second &amp;gt; pos1.second) {&lt;br /&gt;                    found = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(h2 &amp;amp;&amp;amp; pos1.second &amp;lt; u.second &amp;amp;&amp;amp; pos2.second &amp;gt; u.second &amp;amp;&amp;amp;&lt;br /&gt;                    u.first &amp;lt; pos1.first &amp;amp;&amp;amp; vv.first &amp;gt; pos1.first) {&lt;br /&gt;                        found = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;                } &lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(found) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;     &lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ns = s.status | (1&amp;lt;&amp;lt;slot_it-&amp;gt;second);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(v[ns] == 0) {&lt;br /&gt;                v[ns] = 1;&lt;br /&gt;                Q.push(State(ns, 0, s.step+1));&lt;br /&gt;            }           &lt;br /&gt;        }        &lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt; []v;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// pre-calculate stump pairs, log positin, etc...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; get_adj(&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; m[15][15], map&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, ii&amp;gt; &amp;amp;stumppos, map&amp;lt;ii,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; &amp;amp;stumplist,&lt;br /&gt;             map&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, ii&amp;gt; &amp;amp;slotpos, map&amp;lt;ii,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; &amp;amp;slotlist, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &amp;amp;slot_status,&lt;br /&gt;             &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;amp; start, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;amp; dest, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nrow, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ncol) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;short&lt;/span&gt; MAXDIR = 4;&lt;br /&gt;    &lt;span style="color: #008000"&gt;//   down, up, left, right&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;short&lt;/span&gt; dx[MAXDIR] = {1,-1,0, 0};&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;short&lt;/span&gt; dy[MAXDIR] = {0, 0,-1,1};&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;  dl[MAXDIR] = {'|', '|', '-', '-'};&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; nrow; ++i)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; ncol; ++j)&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(m[i][j] == 'S' || m[i][j] == 'E' || m[i][j] == 'B') {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(m[i][j] == 'B') start = stumplist.size();&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(m[i][j] == 'E') dest  = stumplist.size();&lt;br /&gt;                stumplist.insert(make_pair(ii(i,j), stumplist.size()));&lt;br /&gt;                stumppos.insert(make_pair(stumplist.size()-1, ii(i,j)));&lt;br /&gt;            }&lt;br /&gt;    &lt;span style="color: #008000"&gt;// for each stump, scan for available slot to put down logs&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; stumplist.size(); ++j){&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x = stumppos[j].first;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y = stumppos[j].second;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; flag;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; MAXDIR; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nx = x, ny = y;&lt;br /&gt;            flag = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;do&lt;/span&gt;{&lt;br /&gt;                nx = nx + dx[i];&lt;br /&gt;                ny = ny + dy[i];&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(nx&amp;lt;0 || nx &amp;gt;= nrow || ny &amp;lt; 0 || ny &amp;gt;= ncol) {&lt;br /&gt;                    flag = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(m[nx][ny] == 'S' || m[nx][ny] == 'E' || m[nx][ny] == 'B') &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;            } &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(flag) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; logLen = max(abs(nx-x), abs(ny-y));&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(logLen &amp;gt; 1 &amp;amp;&amp;amp; (m[nx][ny] == 'S' || m[nx][ny] == 'E' || m[nx][ny] == 'B')) {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; idnext = stumplist[ii(nx,ny)];&lt;br /&gt;                ii logpos = j &amp;lt; idnext? ii(j, idnext) : ii(idnext, j);&lt;br /&gt;                slotlist.insert(make_pair(logpos, slotlist.size()));&lt;br /&gt;                slotpos.insert(make_pair(slotlist.size()-1, logpos));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; totalslots = slotlist.size();&lt;br /&gt;    &lt;br /&gt;    slot_status = 0;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// scan for existing logs&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; stumplist.size(); ++j){&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x = stumppos[j].first;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y = stumppos[j].second;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; flag;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; MAXDIR; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nx = x, ny = y;&lt;br /&gt;            flag = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;do&lt;/span&gt;{&lt;br /&gt;                nx = nx + dx[i];&lt;br /&gt;                ny = ny + dy[i];&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(nx&amp;lt;0 || nx &amp;gt;= nrow || ny &amp;lt; 0 || ny &amp;gt;= ncol) flag = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;            } &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(!flag &amp;amp;&amp;amp; m[nx][ny] == dl[i]);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(flag) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; logLen = max(abs(nx-x), abs(ny-y));&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(logLen &amp;gt; 1 &amp;amp;&amp;amp; (m[nx][ny] == 'S' || m[nx][ny] == 'E' || m[nx][ny] == 'B')) {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; idnext = stumplist[ii(nx,ny)];&lt;br /&gt;                ii logpos = j &amp;lt; idnext? ii(j, idnext) : ii(idnext, j);&lt;br /&gt;                slot_status |= (1&amp;lt;&amp;lt; slotlist[logpos]);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; totalslots;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ndata;&lt;br /&gt;    scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;ndata);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; m[15][15]; &lt;span style="color: #008000"&gt;// maze&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; data = 0; data &amp;lt; ndata; data++) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nrow, ncol;&lt;br /&gt;        scanf("&lt;span style="color: #8b0000"&gt;%d %d &lt;/span&gt;", &amp;amp;nrow, &amp;amp;ncol);&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; nrow; ++i)&lt;br /&gt;            scanf("&lt;span style="color: #8b0000"&gt;%s &lt;/span&gt;", &amp;amp;m[i]);&lt;br /&gt;        map&amp;lt;ii, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; stumplist;&lt;br /&gt;        map&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, ii&amp;gt; stumppos;&lt;br /&gt;        map&amp;lt;ii,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; slotlist;&lt;br /&gt;        map&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;,ii&amp;gt; slotpos;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; status, start, dest;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; totalslots = get_adj(m, stumppos, stumplist, slotpos, slotlist, &lt;br /&gt;            status, start, dest, nrow, ncol);&lt;br /&gt;        status |= (start&amp;lt;&amp;lt;totalslots);&lt;br /&gt;        printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", BFS(start, dest, stumppos, slotpos, slotlist, status));&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-4098052846354621197?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4098052846354621197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4098052846354621197'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/bfs.html' title='BFS'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-4139965483769137673</id><published>2008-09-25T21:41:00.001-07:00</published><updated>2008-09-25T21:46:05.030-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><title type='text'>DFS</title><content type='html'>&lt;ul&gt; &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Depth-first_search"&gt;wiki&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.cs.mcgill.ca/~cs251/OldCourses/1997/topic26/#cycles"&gt;class notes on Depth first search&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Applications&lt;/p&gt; &lt;p&gt;Here are some algorithms where DFS is used:  &lt;ul&gt; &lt;li&gt;Finding &lt;a href="http://en.wikipedia.org/wiki/Connected_component_%28graph_theory%29"&gt;connected components&lt;/a&gt;.  &lt;li&gt;Cycle detection.  &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Topological_sorting"&gt;Topological sorting&lt;/a&gt;.  &lt;li&gt;Finding 2-(edge or vertex)-connected components.  &lt;li&gt;Finding &lt;a href="http://en.wikipedia.org/wiki/Strongly_connected_components"&gt;strongly connected components&lt;/a&gt;.  &lt;li&gt;Solving puzzles with only one solution, such as &lt;a href="http://en.wikipedia.org/wiki/Maze"&gt;mazes&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;topcoder: &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=standardTemplateLibrary2"&gt;DFS&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Imagine we have an undirected graph. The simplest way to store a graph in STL is to use the lists of vertices adjacent to each vertex. This leads to the vector&amp;lt; vector&amp;lt;int&amp;gt; &amp;gt; W structure, where W[i] is a list of vertices adjacent to i. Let’s verify our graph is connected via DFS:&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;/*&lt;br /&gt;Reminder from Part 1:&lt;br /&gt;typedef vector&amp;lt;int&amp;gt; vi;&lt;br /&gt;typedef vector&amp;lt;vi&amp;gt; vvi; &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;*&lt;span style="color: #008000"&gt;/&lt;/span&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N; &lt;span style="color: #008000"&gt;// number of vertices &lt;/span&gt;&lt;br /&gt; vvi W; &lt;span style="color: #008000"&gt;// graph &lt;/span&gt;&lt;br /&gt; vi V; &lt;span style="color: #008000"&gt;// V is a visited flag &lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; dfs(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i) { &lt;br /&gt;       &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(!V[i]) { &lt;br /&gt;            V[i] = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;; &lt;br /&gt;            for_each(all(W[i]), dfs); &lt;br /&gt;       } &lt;br /&gt; } &lt;br /&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; check_graph_connected_dfs() { &lt;br /&gt;       &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; start_vertex = 0; &lt;br /&gt;       V = vi(N, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;); &lt;br /&gt;       dfs(start_vertex); &lt;br /&gt;       &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (find(all(V), 0) == V.end()); &lt;br /&gt; } &lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;Problem: topcoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=10077"&gt;CactusCount&lt;/a&gt;&lt;/pre&gt;&lt;pre&gt;用一个cycles[]存每个vertex所在的cycle的数目。用DFS进行cycle detection,每碰到一个cycle,将cycle 内所有元素 cycle[i]++。每一次DFS完毕，这一个connected component 内部如果至少有一个vertex的cycle[i] &amp;gt;= 2，则此component 不是cactus.&lt;/pre&gt;&lt;pre&gt;由于找到每个cycle后要回溯找cycle内所有元素，我们需要保存visit的路径。两种方法&lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;font face="Courier New"&gt;每个元素保存一个parent, p[]可以查到每个元素的parent&lt;/font&gt; &lt;br /&gt;&lt;li&gt;&lt;font face="Courier New"&gt;用一个deque保存整条路径 （编程略简单）&lt;/font&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;font face="Courier New"&gt;下面分别给出了两种实现：&lt;/font&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; vi;&lt;br /&gt;vector&amp;lt;vi&amp;gt;  adj;   &lt;span style="color: #008000"&gt;// adj list&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; vv [201];      &lt;span style="color: #008000"&gt;// visited vertex in DFS;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p[201];        &lt;span style="color: #008000"&gt;// parent of node i&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cycle[201];    &lt;span style="color: #008000"&gt;// # of times in a cycle&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; maxcycle;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; checkmax(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &amp;amp;a, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; b) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(b &amp;gt; a) a = b;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DFS(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; c = 0) {&lt;br /&gt;    vv[i] = 0; &lt;span style="color: #008000"&gt;// visiting&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;//printf("visiting %d\n", i+1);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// visit all neighbors of i&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; adj[i].size(); ++j) {&lt;br /&gt;        &lt;span style="color: #008000"&gt;// get the j-th neighbor: k&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = adj[i][j];&lt;br /&gt;        &lt;span style="color: #008000"&gt;// new vertex, first visit&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(vv[k] == -1) {&lt;br /&gt;            &lt;span style="color: #008000"&gt;// assign i as k's parent&lt;/span&gt;&lt;br /&gt;            p[k] = i;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// visit k&lt;/span&gt;&lt;br /&gt;            DFS(k, n, c);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;// detect a cycle : back edge vv[k] == 0 &lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(vv[k] == 0 &amp;amp;&amp;amp;  k != p[i]) {&lt;br /&gt;            &lt;span style="color: #008000"&gt;// actually if maxcycle &amp;gt;=2 &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// we do not need to mark any more&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// just visit all and leave this component, right?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;//printf("cycle %d ", k+1);&lt;/span&gt;&lt;br /&gt;            cycle[k] ++; checkmax(maxcycle, cycle[k]);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;//printf("%d ", i+1);&lt;/span&gt;&lt;br /&gt;            cycle[i] ++; checkmax(maxcycle, cycle[i]);        &lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; parent = p[i];&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;do&lt;/span&gt; {&lt;br /&gt;                &lt;span style="color: #008000"&gt;//printf("%d ", parent+1);&lt;/span&gt;&lt;br /&gt;                cycle[parent] ++; checkmax(maxcycle, cycle[parent]);&lt;br /&gt;                parent = p[parent];                    &lt;br /&gt;            } &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(parent != k); &lt;br /&gt;            &lt;span style="color: #008000"&gt;//printf("%d \n", k+1);&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    vv[i] = c;&lt;br /&gt;    &lt;span style="color: #008000"&gt;//printf("end visiting %d, max cycle %d\n", i+1, cycle[i]);&lt;/span&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CactusCount::countCacti(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n, vector &amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; edges) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(edges.empty()) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; n;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; edge;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; edges.size(); ++i)&lt;br /&gt;        edge += edges[i];&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; edge.size(); ++i)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(edge[i]==',') edge[i] = ' '; &lt;br /&gt;    &lt;br /&gt;    adj.clear();&lt;br /&gt;    adj.resize(n, vi());&lt;br /&gt;&lt;br /&gt;    memset(vv,-1, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(vv));&lt;br /&gt;    memset(p, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(p));&lt;br /&gt;    memset(cycle, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(cycle));&lt;br /&gt;&lt;br /&gt;    stringstream ss(edge);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a, b;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(ss &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b) {&lt;br /&gt;        --a, --b;&lt;br /&gt;        adj[b].push_back(a) ; adj[a].push_back(b);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cnt = 0, c = 1;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(vv[i] == -1) {&lt;br /&gt;        p[i] = -1;&lt;br /&gt;        maxcycle = 0;&lt;br /&gt;        DFS(i, n, c);&lt;br /&gt;        &lt;span style="color: #008000"&gt;//printf("component %d: %d, size %d\n", c, maxcycle, component[c].size());&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(maxcycle &amp;lt;= 1) ++cnt;&lt;br /&gt;        ++c;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; cnt;&lt;br /&gt;}&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// ----------------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// use deque to save visiting path&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; adj[200];  &lt;span style="color: #008000"&gt;// adj list&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; col[200];          &lt;span style="color: #008000"&gt;// vertex color&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cycles[200];       &lt;span style="color: #008000"&gt;// # of times in a cycle&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; iscacti;          &lt;span style="color: #008000"&gt;// is the current component a cacti&lt;/span&gt;&lt;br /&gt;deque&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; path;       &lt;span style="color: #008000"&gt;// for backtrace&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// visit vertex v whose parent is p&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; dfs(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; p) {&lt;br /&gt;    &lt;span style="color: #008000"&gt;// visiting v&lt;/span&gt;&lt;br /&gt;    col[v] = 1;&lt;br /&gt;    path.push_front(v);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; adj[v].size(); ++j) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = adj[v][j];&lt;br /&gt;        &lt;span style="color: #008000"&gt;// unvisited&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(col[k] == 0) dfs(k, v);&lt;br /&gt;        &lt;span style="color: #008000"&gt;// back edge detected&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(col[k] == 1 &amp;amp;&amp;amp; k != p) {&lt;br /&gt;            deque&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;::iterator root = ++find(ALL(path), k);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(deque&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;::iterator it = path.begin(); it!= root; ++it)&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(++ cycles[*it] &amp;gt; 1) iscacti = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    path.pop_front();&lt;br /&gt;    col[v] = 2;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CactusCount::countCacti(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n, vector &amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; edges) {&lt;br /&gt;    REP(i, n) {&lt;br /&gt;        adj[i].clear(); &lt;br /&gt;        col[i] = cycles[i] = 0;&lt;br /&gt;    }&lt;br /&gt;    stringstream ss;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(vector&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;::iterator it = edges.begin(); it != edges.end(); ++it)&lt;br /&gt;        ss &amp;lt;&amp;lt; *it;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a, b;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(ss &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b) {&lt;br /&gt;        ss.ignore(1); --a, --b;&lt;br /&gt;        adj[b].push_back(a) ; adj[a].push_back(b);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cnt = 0;&lt;br /&gt;    memset(cycles, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(cycles));&lt;br /&gt;    memset(col, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(col));&lt;br /&gt;    REP(i,n) &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(col[i] == 0) {&lt;br /&gt;        iscacti = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;        dfs(i, -1);&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(iscacti) ++cnt;        &lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; cnt;&lt;br /&gt;}&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;Example: &lt;a href="http://lh4.ggpht.com/greeness/SNxoB9X47CI/AAAAAAAAB1Q/tcpgQSn_wq0/image%5B11%5D.png"&gt;&lt;img style="margin: 0px 95px 0px 5px" height="302" alt="image" src="http://lh3.ggpht.com/greeness/SNxoCKguUFI/AAAAAAAAB1U/u95ddavYJ24/image_thumb%5B9%5D.png" width="471" align="right"&gt;&lt;/a&gt;DFS visiting log&lt;/pre&gt;&lt;pre&gt;-----------------------------------&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;visiting 1&lt;br&gt;visiting 2&lt;br&gt;visiting 3&lt;br&gt;visiting 4&lt;br&gt;visiting 5&lt;br&gt;cycle 3 5 4 3&lt;br&gt;end visiting 5, max cycle 1&lt;br&gt;end visiting 4, max cycle 1&lt;br&gt;cycle 1 3 2 1&lt;br&gt;end visiting 3, max cycle 2&lt;br&gt;end visiting 2, max cycle 1&lt;br&gt;end visiting 1, max cycle 1&lt;br&gt;------------------------------------&lt;br&gt;component 1: maxcycle 2&lt;br&gt;------------------------------------&lt;br&gt;visiting 6&lt;br&gt;visiting 7&lt;br&gt;visiting 8&lt;br&gt;cycle 6 8 7 6&lt;br&gt;visiting 9&lt;br&gt;visiting 10&lt;br&gt;visiting 11&lt;br&gt;cycle 9 11 10 9&lt;br&gt;end visiting 11, max cycle 1&lt;br&gt;end visiting 10, max cycle 1&lt;br&gt;end visiting 9, max cycle 1&lt;br&gt;end visiting 8, max cycle 1&lt;br&gt;end visiting 7, max cycle 1&lt;br&gt;end visiting 6, max cycle 1&lt;br&gt;------------------------------------&lt;br&gt;component 2: maxcycle 1&lt;br&gt;------------------------------------&lt;br&gt;visiting 12&lt;br&gt;visiting 13&lt;br&gt;end visiting 13, max cycle 0&lt;br&gt;end visiting 12, max cycle 0&lt;br&gt;------------------------------------&lt;br&gt;component 3: maxcycle 0&lt;br&gt;------------------------------------&lt;br&gt;visiting 14&lt;br&gt;visiting 15&lt;br&gt;visiting 16&lt;br&gt;visiting 17&lt;br&gt;cycle 14 17 16 15 14&lt;br&gt;end visiting 17, max cycle 1&lt;br&gt;cycle 14 16 15 14&lt;br&gt;end visiting 16, max cycle 2&lt;br&gt;end visiting 15, max cycle 2&lt;br&gt;end visiting 14, max cycle 2&lt;br&gt;------------------------------------&lt;br&gt;component 4: maxcycle 2&lt;br&gt;------------------------------------&lt;br&gt;Test Case #3...PASSED&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-4139965483769137673?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4139965483769137673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4139965483769137673'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/dfs.html' title='DFS'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/greeness/SNxoCKguUFI/AAAAAAAAB1U/u95ddavYJ24/s72-c/image_thumb%5B9%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-6991713518507462520</id><published>2008-09-24T15:13:00.001-07:00</published><updated>2008-09-24T15:13:20.621-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><title type='text'>Dijkstra: single source shortest path</title><content type='html'>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm"&gt;Wiki&lt;/a&gt;: Dijkstra algorithm is a &lt;a href="http://en.wikipedia.org/wiki/Graph_search_algorithm"&gt;graph search algorithm&lt;/a&gt; that solves the single-source &lt;a href="http://en.wikipedia.org/wiki/Shortest_path_problem"&gt;shortest path problem&lt;/a&gt; for a &lt;a href="http://en.wikipedia.org/wiki/Graph_%28mathematics%29"&gt;graph&lt;/a&gt; with non negative &lt;a href="http://en.wikipedia.org/wiki/Edge_%28graph_theory%29"&gt;edge&lt;/a&gt; path costs, outputting a &lt;a href="http://en.wikipedia.org/wiki/Shortest_path_tree"&gt;shortest path tree&lt;/a&gt;. This algorithm is often used in &lt;a href="http://en.wikipedia.org/wiki/Routing"&gt;routing&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;topCoder: &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=standardTemplateLibrary2"&gt;Dijstra via priority_queue&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Dijkstra&lt;br&gt;In the last part of this tutorial I’ll describe how to efficiently implement Dijktra’s algorithm in sparse graph using STL containers. Please look through &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=graphsDataStrucs3#dijkstra"&gt;this tutorial&lt;/a&gt; for information on Dijkstra’s algoritm. Consider we have a weighted directed graph that is stored as vector&amp;lt; vector&amp;lt; pair&amp;lt;int,int&amp;gt; &amp;gt; &amp;gt; G, where &lt;/p&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;G.size() is the number of vertices in our graph  &lt;li&gt;G[i].size() is the number of vertices directly reachable from vertex with index i  &lt;li&gt;G[i][j].first is the index of j-th vertex reachable from vertex i  &lt;li&gt;G[i][j].second is the length of the edge heading from vertex i to vertex G[i][j].first&lt;/li&gt;&lt;/ul&gt; &lt;blockquote&gt; &lt;p&gt;We assume this, as defined in the following two code snippets: &lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; pair&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; ii;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; vector&amp;lt;ii&amp;gt; vii;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; vector&amp;lt;vii&amp;gt; vvii;&lt;/pre&gt;&lt;pre&gt;#define tr(c,i) &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(typeof((c).begin() i = (c).begin(); i != (c).end(); i++) &lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;      vi D(N, 987654321); &lt;br /&gt;      &lt;span style="color: #008000"&gt;// distance from start vertex to each vertex&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      priority_queue&amp;lt;ii,vector&amp;lt;ii&amp;gt;, greater&amp;lt;ii&amp;gt; &amp;gt; Q; &lt;br /&gt;      &lt;span style="color: #008000"&gt;// priority_queue with reverse comparison operator, &lt;/span&gt;&lt;br /&gt;      &lt;span style="color: #008000"&gt;// so top() will return the least distance&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: #008000"&gt;// initialize the start vertex, suppose it¡¯s zero&lt;/span&gt;&lt;br /&gt;      D[0] = 0;&lt;br /&gt;      Q.push(ii(0,0));&lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #008000"&gt;// iterate while queue is not empty&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(!Q.empty()) {&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// fetch the nearest element&lt;/span&gt;&lt;br /&gt;            ii top = Q.top();&lt;br /&gt;            Q.pop();&lt;br /&gt;                        &lt;br /&gt;            &lt;span style="color: #008000"&gt;// v is vertex index, d is the distance&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v = top.second, d = top.first;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// this check is very important&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// we analyze each vertex only once&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// the other occurrences of it on queue (added earlier) &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// will have greater distance&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(d &amp;lt;= D[v]) {&lt;br /&gt;                  &lt;span style="color: #008000"&gt;// iterate through all outcoming edges from v&lt;/span&gt;&lt;br /&gt;                  tr(G[v], it) {&lt;br /&gt;                        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; v2 = it-&amp;gt;first, cost = it-&amp;gt;second;&lt;br /&gt;                        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(D[v2] &amp;gt; D[v] + cost) {&lt;br /&gt;                              &lt;span style="color: #008000"&gt;// update distance if possible&lt;/span&gt;&lt;br /&gt;                              D[v2] = D[v] + cost;&lt;br /&gt;                              &lt;span style="color: #008000"&gt;// add the vertex to queue&lt;/span&gt;&lt;br /&gt;                              Q.push(ii(D[v2], v2));&lt;br /&gt;&lt;br /&gt;                        }&lt;br /&gt;                  }&lt;br /&gt;            }&lt;br /&gt;      }&lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;Problems: &lt;/pre&gt;&lt;pre&gt;UVa 429 - &lt;a href="http://acm.uva.es/p/v4/429.html"&gt;Word Transformation&lt;/a&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-6991713518507462520?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/6991713518507462520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/6991713518507462520'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/dijkstra-single-source-shortest-path.html' title='Dijkstra: single source shortest path'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-8685552033890064577</id><published>2008-09-23T20:35:00.001-07:00</published><updated>2008-09-23T20:36:07.136-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><title type='text'>Flood Fill</title><content type='html'>&lt;p&gt;The idea is to find the node that has not been assigned to a component. Flood fill can be performed in two ways, both O(N+M): &lt;/p&gt; &lt;ul&gt; &lt;li&gt;depth-first: assign unvisited neighbors to the current component and recurses on them.&lt;/li&gt; &lt;li&gt;breadth-first: no recursion, all the unvisited neighbors are push onto a queue. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Problems:&lt;/p&gt; &lt;p&gt;UVa 352: &lt;a href="http://acm.uva.es/p/v3/352.html"&gt;The Seasonal War&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; dx[] = {-1, 0, 0, 1, 1, -1, 1, -1};&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; dy[] = {0 , -1,1, 0, 1, -1, -1, 1};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; visit(vector&amp;lt;vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; &amp;gt; &amp;amp;V, vector&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; &amp;amp;M, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j) {&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N = V.size();&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(i &amp;lt; 0 || i &amp;gt;= N || j &amp;lt; 0 || j &amp;gt;= N) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; ;&lt;br /&gt;&lt;br /&gt;	&lt;span style="color: #008000"&gt;// '0' pixel or  visited already&lt;/span&gt;&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(M[i][j] == '0' || V[i][j] &amp;gt; 0) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; ;&lt;br /&gt;	&lt;br /&gt;	V[i][j] = 1; &lt;br /&gt;	&lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = 0; k &amp;lt; 8; ++k)&lt;br /&gt;		visit(V, M, i+dx[k], j+dy[k]);&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; flood_fill(vector&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; &amp;amp;M) {&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N = M.size();&lt;br /&gt;	vector&amp;lt;vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; &amp;gt; V(N, vector&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;(N, -1));&lt;br /&gt;	&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ncomp = 0; &lt;span style="color: #008000"&gt;// number of components&lt;/span&gt;&lt;br /&gt;	&lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; N; ++i)&lt;br /&gt;		&lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; N; ++j) {&lt;br /&gt;			&lt;span style="color: #008000"&gt;// the pixel contains "1" and it has not been visited&lt;/span&gt;&lt;br /&gt;			&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(M[i][j] == '1' &amp;amp;&amp;amp; V[i][j] == -1) {&lt;br /&gt;				ncomp ++;&lt;br /&gt;				&lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = 0; k &amp;lt; 8; ++k)&lt;br /&gt;					visit(V, M, i+dx[k], j+dy[k]);&lt;br /&gt;			}&lt;br /&gt;		}&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; ncomp;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;UVa 572: &lt;a href="http://acm.uva.es/p/v5/572.html"&gt;Oil Deposits&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;topCoder: &lt;strong&gt;&lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=9752&amp;amp;rd=12183" name="9752"&gt;HoleCakeCuts&lt;/a&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm411"&gt;Editorial&lt;/a&gt;:&lt;/p&gt;&lt;br /&gt;&lt;h5&gt;Approach 1&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Flood-filling by Depth-first search (DFS) or Breadth-first search (BFS) is used to count the number of pieces. The cake can be divided into many unit squares (each has a side length of 1), and a piece is a maximal connected group of unit squares which has the property that no common border (if existing) between any two squares in the group lies on a cut. So from a unit square of some piece we can visit all other unit squares belonging to that piece by limiting DFS or BFS not to cross any cut while travelling between squares. See &lt;a href="http://www.topcoder.com/tc?module=MemberProfile&amp;amp;cr=10574855&amp;amp;tab=alg"&gt;Petr&lt;/a&gt;'s &lt;a href="http://www.topcoder.com/stat?c=problem_solution&amp;amp;rm=298121&amp;amp;rd=12183&amp;amp;pm=9752&amp;amp;cr=10574855"&gt;solution&lt;/a&gt; for a clean implementation of this approach. &lt;br /&gt;&lt;h5&gt;Approach 3&lt;img style="margin: 0px 0px 0px 5px" height="205" alt="srm411_holecakecuts_approach_3.jpg" src="http://www.topcoder.com/i/education/srm411_holecakecuts_approach_3.jpg" width="240" align="right"&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Another approach which has a smaller time complexity is to reduce the original problem to a problem with a cake and no hole. This can be done by finding two horizontal cuts: &lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;the horizontal cut which is inside the hole and closest to the top side of the hole. It can be the cut going through the top side of the hole. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;the horizontal cut which is inside the hole and closest to the bottom side of the hole. It can be the cut going through the bottom side of the hole. &lt;/li&gt;&lt;/ol&gt;These two cuts (which may be the same cut) together with the vertical sides of the hole divide the outer square of the cake into four rectangles each of which can be considered as a cake with no hole. The fifth rectangle in the center always contains no pieces. The four rectangles are colored differently in the following illustration: &lt;br /&gt;&lt;p&gt;If the two horizontal cuts of interest cannot be found, we can search for two vertical cuts with similar properties. And if, again, we cannot find the cuts, we can safely remove the hole from the original cake to obtain a reduced problem. &lt;br /&gt;&lt;p&gt;Solving a reduced problem is trivial. We just count the numbers of horizontal and vertical cuts which completely cut through the cake (not going through any border of the cake), add one to each number, and then multiply them together to get the number of pieces. &lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-8685552033890064577?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8685552033890064577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8685552033890064577'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/flood-fill.html' title='Flood Fill'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-8521951497746845669</id><published>2008-09-22T18:17:00.001-07:00</published><updated>2008-09-23T18:22:27.626-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>C++ Effective notes</title><content type='html'>&lt;p&gt;Intro  &lt;ul&gt; &lt;li&gt;object的定义式是编译器为它配置内存的起点。  &lt;li&gt;如果你想要产生一个对象数组，但该对象型别没有提供default constructor, 通常的做法是定义一个指针数组取而代之，然后利用new一一将每个指针初始化。  &lt;ul&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;//class Automobile&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Autos { &lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;: &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cost; &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; features; &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; fixTimes; &lt;br /&gt;  Autos(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; c, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; f, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; fix): cost(c), features(f), fixTimes(fix){} &lt;br /&gt;  &lt;span style="color: #008000"&gt;// ...&lt;/span&gt;&lt;br /&gt;}; &lt;br /&gt;&lt;br /&gt;Autos *ptrArray[10]; &lt;br /&gt;ptrArray[0] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Autos(10000,3,2); &lt;br /&gt;ptrArray[1] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Autos(50000,2,10); &lt;br /&gt;&lt;span style="color: #008000"&gt;//...&lt;/span&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;copy constructor: 以某对象作为另一个同型对象的初值 &lt;br /&gt;&lt;ul&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;                                   string&lt;/span&gt; s1; &lt;span style="color: #008000"&gt;// default constructor &lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; s2(s1); &lt;span style="color: #008000"&gt;// copy constructor &lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; s2 = s1; &lt;span style="color: #008000"&gt;// copy constructor &lt;/span&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;pass-by-value 是calling copy constructor的同义词 &lt;br /&gt;&lt;li&gt;纯粹从操作的观点来看，initialization &amp;amp; assignment之间的差异在于前者由constructor执行，后者由operator=执行。两个动作对应不同的函数动作。C++严格区分两者，是因为上述两个函数考虑的事情不同。constructor通常必须检验其引数的validity, 大部分assignment运算符不必如此。assignment运算符认定其参数是合法的，它会检测诸如“自己赋值给自己”这样的病态情况，以及配置新内存之前先释放旧有内存。 &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Item 1: Prefer const and inline to #define. &lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;Item 2: Prefer &amp;lt;iostream&amp;gt; to &amp;lt;stdio.h&amp;gt; &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;Item 3: Prefer new and delete to malloc and free. &lt;br /&gt;&lt;p&gt;Item 4: Prefer C++-style comments. &lt;br /&gt;&lt;p&gt;Item 5: Use the same form in corresponding uses of new and delete. &lt;br /&gt;&lt;p&gt;Item 6: Use delete on pointer members in destructors. &lt;br /&gt;&lt;p&gt;adding a pointer member almost always requires each of the following: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Initialization of the pointer in each of the constructors. If no memory is to be allocated to the pointer in a particular constructor, the pointer should be initialized to 0 (i.e., the null pointer). &lt;br /&gt;&lt;li&gt;Deletion of the existing memory and assignment of new memory in the assignment operator. (See also Item 17.) &lt;br /&gt;&lt;li&gt;Deletion of the pointer in the destructor. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Item 7: Be prepared for out-of-memory conditions. &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;The base class part of the design lets derived classes inherit the set_new_handler &lt;br&gt;and operator new functions they all need, while the template part of the design ensures that each inheriting class gets a different currentHandler data member. &lt;br /&gt;&lt;ul&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;template&lt;/span&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; T&amp;gt;&lt;span style="color: #008000"&gt;// "mixin-style" base class&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; NewHandlerSupport {&lt;span style="color: #008000"&gt;// for class-specific&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;span style="color: #008000"&gt;// set_new_handler support &lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; new_handler set_new_handler(new_handler p); &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; * &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;(size_t size);&lt;br /&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;: &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; new_handler currentHandler;};&lt;br /&gt;  &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;template&lt;/span&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; T&amp;gt;&lt;br /&gt;  new_handler NewHandlerSupport&amp;lt;T&amp;gt;::set_new_handler(new_handler p)&lt;br /&gt;  { &lt;br /&gt;    new_handler oldHandler = currentHandler; currentHandler = p; &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; oldHandler;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;template&lt;/span&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; T&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; * NewHandlerSupport&amp;lt;T&amp;gt;::&lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;(size_t size)&lt;br /&gt;{ &lt;br /&gt;  new_handler globalHandler = &lt;br /&gt;    std::set_new_handler(currentHandler); &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; *memory;  &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {   &lt;br /&gt;    memory = ::&lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;(size); &lt;br /&gt;  } &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (std::bad_alloc&amp;amp;) {   &lt;br /&gt;    std::set_new_handler(globalHandler);   &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt;; &lt;br /&gt;  } &lt;br /&gt;  std::set_new_handler(globalHandler); &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; memory;&lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;}&lt;br /&gt;  &lt;br /&gt;&lt;span style="color: #008000"&gt;// this sets each currentHandler to 0template&amp;lt;class T&amp;gt;&lt;/span&gt;&lt;br /&gt;new_handler NewHandlerSupport&amp;lt;T&amp;gt;::currentHandler;&lt;/pre&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Item 8: Adhere to convention when writing operator new and operator delete. &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;pseudocode for a non-member operator new looks like this:&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; * &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;(size_t size) &lt;span style="color: #008000"&gt;// your operator new might&lt;/span&gt;&lt;br /&gt;{ &lt;span style="color: #008000"&gt;// take additional params &lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (size == 0) { &lt;span style="color: #008000"&gt;// handle 0-byte requests   &lt;/span&gt;&lt;br /&gt;    size = 1; &lt;span style="color: #008000"&gt;// by treating them as &lt;/span&gt;&lt;br /&gt;  } &lt;span style="color: #008000"&gt;// 1-byte requests &lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; (1) {   &lt;br /&gt;    attempt to allocate size   bytes;   &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (the allocation was successful)     &lt;br /&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (a pointer to the memory);   &lt;br /&gt;    &lt;span style="color: #008000"&gt;// allocation was unsuccessful; find out what the   &lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// current error-handling function is (see Item 7)    &lt;/span&gt;&lt;br /&gt;    new_handler globalHandler = set_new_handler(0);   &lt;br /&gt;    set_new_handler(globalHandler);   &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (globalHandler) (*globalHandler)();   &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; std::bad_alloc(); &lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Item 7 remarks that operator new contains an infinite loop, and the code above shows that loop explicitly. while (1) is about as infinite as it gets. The only way out of the loop is for memory to be successfully allocated or for the new-handling function to do one of the things described in Item 7: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;make more memory available, &lt;br /&gt;&lt;li&gt;install a different new-handler, &lt;br /&gt;&lt;li&gt;deinstall the new-handler, &lt;br /&gt;&lt;li&gt;throw an exception of or derived from std::bad_alloc, &lt;br /&gt;&lt;li&gt;or fail to return. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;It should now be clear why the new-handler must do one of those things. If it doesn't, the loop inside operator new will never terminate. &lt;br /&gt;&lt;p&gt;pseudocode for a non-member operator delete:&lt;pre&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delete&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; *rawMemory)&lt;br /&gt;{ &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (rawMemory == 0) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;; &lt;span style="color: #008000"&gt;// do nothing if the null &lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #008000"&gt;// pointer is being deleted &lt;/span&gt;&lt;br /&gt;  deallocate the memory pointed to by rawMemory; &lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Item 9: Avoid hiding the "normal" form of new. &lt;br /&gt;&lt;p&gt;Item 10: Write operator delete if you write operator new. &lt;br /&gt;&lt;h3&gt;Item 11: Declare a copy constructor and an assignment operator for classes with dynamically allocated memory. &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;if a class has dynamically allocated memory, but it has no copy consturctor and no assignment operator.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&lt;a href="http://lh5.ggpht.com/greeness/SNiCXrp2zwI/AAAAAAAABz8/C78LIfNzBH8/image%5B8%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="119" alt="image" src="http://lh3.ggpht.com/greeness/SNiCXwhnn1I/AAAAAAAAB0A/8dfr4rdeK7k/image_thumb%5B2%5D.png" width="244" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="http://lh3.ggpht.com/greeness/SNiCYFoC5nI/AAAAAAAAB0E/6X3dtK_nqM8/image%5B11%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="93" alt="image" src="http://lh3.ggpht.com/greeness/SNiCYSuJAqI/AAAAAAAAB0I/CGe1gY_soKM/image_thumb%5B3%5D.png" width="244" border="0"&gt;&lt;/a&gt; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;b = a;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;after the assignment operation, the memory that contains "World\0" is lost! &lt;/p&gt;&lt;br /&gt;&lt;p&gt;the internal pointers in a and b both point to "Hello\0". If a's destructor is called, memory "Hello" is deleted, while b's pointer is still pointing to that memory!&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Write your own versions of the copy constructor&amp;nbsp; and the assignment operator if you have any pointers in your class. Inside those functions, you can either copy the&lt;br&gt;pointed-to data structures so that every object has its own copy, or you can implement some kind of reference-counting scheme (see Item M29) to keep track of how many objects are currently pointing to a particular data structure. &lt;br /&gt;&lt;h3&gt;Item 12: Prefer initialization to assignment in constructors. &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;There are times when the initialization list must be used. In particular, &lt;font color="#0080ff"&gt;const&lt;/font&gt; and &lt;font color="#0080ff"&gt;reference&lt;/font&gt; members may only be initialized, never assigned. &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;template&lt;/span&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; T&amp;gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; NamedPtr {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;  NamedPtr(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;amp; initName, T *initPtr);&lt;br /&gt;  &lt;span style="color: #008000"&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name;&lt;br /&gt;  T * &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; ptr;&lt;br /&gt;};&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;This class definition requires that you use a &lt;font color="#0080ff"&gt;member initialization list&lt;/font&gt;, because const members may only be initialized, never assigned. So, &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;template&lt;/span&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; T&amp;gt;&lt;br /&gt;NamedPtr&amp;lt;T&amp;gt;::NamedPtr(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;amp; initName, T *initPtr )&lt;br /&gt;: name(initName), ptr(initPtr)&lt;br /&gt;{}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;instead of&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;template&lt;/span&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; T&amp;gt;&lt;br /&gt;NamedPtr&amp;lt;T&amp;gt;::NamedPtr(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;amp; initName, T *initPtr)&lt;br /&gt;{&lt;br /&gt;  name = initName;&lt;br /&gt;  ptr = initPtr;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Note that static class members should &lt;font color="#0080ff"&gt;never&lt;/font&gt; be initialized in a class's constructor. Static members are initialized&lt;br&gt;only once per program run, so it makes no sense to try to "initialize" them each time an object of the class's type&lt;br&gt;is created. &lt;br /&gt;&lt;p&gt;Item 13: List members in an initialization list in the order in which they are declared. &lt;br /&gt;&lt;h3&gt;Item 14: Make sure base classes have virtual destructors. &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;When you try to delete a derived class object through a base class pointer and the base class has a nonvirtual destructor, the results are&lt;br&gt;undefined. &lt;br /&gt;&lt;p&gt;Item 15: Have operator= return a reference to *this. &lt;br /&gt;&lt;p&gt;Item 16: Assign to all data members in operator=. &lt;br /&gt;&lt;h3&gt;Item 17: Check for assignment to self in operator=. &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/greeness/SNiCYpQwd2I/AAAAAAAAB0M/_F1UuBQPrtU/image%5B5%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="94" alt="image" src="http://lh4.ggpht.com/greeness/SNiCY0GgHfI/AAAAAAAAB0Q/DYzRKqGTExs/image_thumb%5B1%5D.png" width="244" border="0"&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/greeness/SNiCey_3D2I/AAAAAAAAB0U/hzLgfHMHP9U/image%5B2%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="94" alt="image" src="http://lh6.ggpht.com/greeness/SNiCfT70-yI/AAAAAAAAB0Y/VPu-YYVL5x4/image_thumb.png" width="244" border="0"&gt;&lt;/a&gt; &lt;br /&gt;&lt;p&gt;A more important reason for checking for assignment to self is to ensure correctness. Remember that an&lt;br&gt;assignment operator must typically free the resources allocated to an object (i.e., get rid of its old value) before it can allocate the new resources corresponding to its new value. When assigning to self, this freeing of resources can be disastrous, because the old resources might be needed during the process of allocating the new ones. &lt;br /&gt;&lt;h3&gt;Item 18: Strive for class interfaces that are complete and minimal. &lt;/h3&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// return element for read/write&lt;/span&gt;&lt;br /&gt;T&amp;amp; &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt;[](&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; index);&lt;br /&gt;&lt;span style="color: #008000"&gt;// return element for read-only&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; T&amp;amp; &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt;[](&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; index) &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;By declaring the same function twice, once const and once non-const, you provide support for both const and non-const Array objects.&lt;br /&gt;&lt;p&gt;Item 19: Differentiate among member functions, non-member functions, and friend functions. &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Rational {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;  Rational(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; numerator = 0, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; denominator = 1);&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; numerator() &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; denominator() &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; Rational &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt;*(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; Rational&amp;amp; rhs) &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: #008000"&gt;//...&lt;/span&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Rational oneEighth(1, 8);&lt;br /&gt;Rational oneHalf(1, 2);&lt;br /&gt;Rational result = oneHalf * oneEighth; &lt;span style="color: #008000"&gt;// fine&lt;/span&gt;&lt;br /&gt;result = result * oneEighth; &lt;span style="color: #008000"&gt;// fine&lt;/span&gt;&lt;br /&gt;result = oneHalf * 2; &lt;span style="color: #008000"&gt;// fine&lt;/span&gt;&lt;br /&gt;result = 2 * oneHalf; &lt;span style="color: #008000"&gt;// error!&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;隐式转换可以在 non-explicite constructor 的 parameter listed in the function declaration&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color: #008000"&gt;// declare this globally or within a namespace; see&lt;/span&gt;&lt;br&gt;&lt;span style="color: #008000"&gt;// Item M20 for why it's written as it is&lt;/span&gt;&lt;br&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; Rational &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt;*(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; Rational&amp;amp; lhs,&lt;br&gt;&lt;span style="color: #0000ff"&gt; const&lt;/span&gt; Rational&amp;amp; rhs)&lt;br&gt;{&lt;br&gt;&amp;nbsp; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Rational(lhs.numerator() * rhs.numerator(),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; lhs.denominator() * rhs.denominator());&lt;br&gt;}&lt;br&gt;&lt;br&gt;Rational oneFourth(1, 4);&lt;br&gt;Rational result;&lt;br&gt;result = oneFourth * 2; &lt;span style="color: #008000"&gt;// fine&lt;/span&gt;&lt;br&gt;result = 2 * oneFourth; &lt;span style="color: #008000"&gt;// hooray, it works!&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Lessons: (assume f is the function you're trying to declare properly and C is the class to which it is conceptually related )&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Virtual functions must be members. If f needs to be virtual, make it a member function of C.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;operator&amp;gt;&amp;gt; and operator&amp;lt;&amp;lt; are never members. If f is operator&amp;gt;&amp;gt; or operator&amp;lt;&amp;lt;, make f a non-member function. If, in addition, f needs access to non-public members of C, make f a friend of C.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Only non-member functions get type conversions on their left-most argument. If f needs type&lt;br&gt;conversions on its left-most argument, make f a non-member function. If, in addition, f needs access to&lt;br&gt;non-public members of C, make f a friend of C.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Everything else should be a member function. If none of the other cases apply, make f a member&lt;br&gt;function of C.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Item 20: Avoid data members in the public interface. &lt;br /&gt;&lt;h3&gt;Item 21: Use const whenever possible. &lt;/h3&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *p = "&lt;span style="color: #8b0000"&gt;Hello&lt;/span&gt;"; &lt;span style="color: #008000"&gt;// non-const pointer, non-const data&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *p = "&lt;span style="color: #8b0000"&gt;Hello&lt;/span&gt;"; &lt;span style="color: #008000"&gt;// non-const pointer, const data&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; * &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; p = "&lt;span style="color: #8b0000"&gt;Hello&lt;/span&gt;"; &lt;span style="color: #008000"&gt;// const pointer, non-const data&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; * &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; p = "&lt;span style="color: #8b0000"&gt;Hello&lt;/span&gt;"; &lt;span style="color: #008000"&gt;// const pointer, const data&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Basically, you mentally draw a vertical line through the asterisk of a pointer declaration, and if the word const appears to the left of the line, what's pointed to is constant; if the word const appears to the right of the line, the pointer itself is constant; if const appears on both sides of the line, both are constant.&lt;br /&gt;&lt;p&gt;Some of the most powerful uses of const stem from its application to function declarations. Within a function declaration, const can refer to the function's return value, to individual parameters, and, for member functions, to the function as a whole.&lt;br /&gt;&lt;p&gt;Item 22: Prefer pass-by-reference to pass-by-value. &lt;br /&gt;&lt;h3&gt;Item 23: Don't try to return a reference when you must return an object. &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;when deciding between returning a reference and returning an object, your job is to make the choice that does the right thing. Let your compiler vendors wrestle with figuring out how to make that&lt;br&gt;choice as inexpensive as possible.&lt;br /&gt;&lt;p&gt;Item 24: Choose carefully between function overloading and parameter defaulting. &lt;br /&gt;&lt;p&gt;The confusion over function overloading and parameter defaulting stems from the fact that they both allow a single function name to be called in more than one way.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; f(); &lt;span style="color: #008000"&gt;// f is overloaded&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; f(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x);&lt;br /&gt;f(); &lt;span style="color: #008000"&gt;// calls f()&lt;/span&gt;&lt;br /&gt;f(10); &lt;span style="color: #008000"&gt;// calls f(int)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; g(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x = 0); &lt;span style="color: #008000"&gt;// g has a default&lt;/span&gt;&lt;span style="color: #008000"&gt; parameter value&lt;/span&gt;&lt;br /&gt;g(); &lt;span style="color: #008000"&gt;// calls g(0)&lt;/span&gt;&lt;br /&gt;g(10); &lt;span style="color: #008000"&gt;// calls g(10)&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;The answer depends on two other questions. First, is there a value you can use for a default? Second, how many algorithms do you want to use? In general, if you can choose a reasonable default value and you want to employ only a single algorithm, you'll use default parameters (see also Item 38). Otherwise you'll use function overloading.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// A class for representing natural numbers&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Natural {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;  Natural(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; initValue);&lt;br /&gt;  Natural(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; Natural&amp;amp; rhs);&lt;br /&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; value;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; init(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; initValue);&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; error(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;amp; msg);&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Natural::init(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; initValue) { &lt;br /&gt;  value = initValue; &lt;br /&gt;}&lt;br /&gt;Natural::Natural(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; initValue) {&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (initValue &amp;gt; 0) init(initValue);&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; error("&lt;span style="color: #8b0000"&gt;Illegal initial value&lt;/span&gt;");&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; Natural::Natural(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; Natural&amp;amp; x) { &lt;br /&gt;  init(x.value); &lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;The constructor taking an int has to perform error checking, but the copy constructor doesn't, so two different functions are needed. That means overloading. However, note that both functions must assign an initial value for the new object. This could lead to code duplication in the two constructors, so you maneuver around that problem by writing a private member function init that contains the code common to the two constructors. This tactic using overloaded functions that call a common underlying function for some of their work is worth remembering, because it's frequently useful (see e.g., Item 12).&lt;br /&gt;&lt;p&gt;Item 25: Avoid overloading on a pointer and a numerical type. &lt;br /&gt;&lt;p&gt;Item 26: Guard against potential ambiguity. &lt;br /&gt;&lt;p&gt;Item 27: Explicitly disallow use of implicitly generated member functions you don't want. &lt;br /&gt;&lt;p&gt;Item 28: Partition the global namespace.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Item 29: Avoid returning "handles" to internal data.&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/greeness/SNmV5FghpxI/AAAAAAAAB0c/-jABGMDrb4g/image%5B4%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="100" alt="image" src="http://lh4.ggpht.com/greeness/SNmV5_SvKnI/AAAAAAAAB0g/Bv5ApCUEMmc/image_thumb%5B2%5D.png" width="312" border="0"&gt;&lt;/a&gt; &lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; String {&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;:&lt;br /&gt;  String(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *value); &lt;span style="color: #008000"&gt;// see Item 11 for pos-&lt;/span&gt;&lt;br /&gt;  ~String(); &lt;span style="color: #008000"&gt;// sible implementations;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #008000"&gt;// see Item M5 for comments &lt;/span&gt;&lt;span style="color: #008000"&gt;on the first constructor&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *() &lt;span style="color: #0000ff"&gt;const&lt;/span&gt;; &lt;span style="color: #008000"&gt;// convert String -&amp;gt; char*;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #008000"&gt;// see also Item M5&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #008000"&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *data;&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; String B("&lt;span style="color: #8b0000"&gt;Hello World&lt;/span&gt;"); &lt;span style="color: #008000"&gt;// B is a const object&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; * str = B;&lt;br /&gt;strcpy(str, "&lt;span style="color: #8b0000"&gt;Hi Mom&lt;/span&gt;");&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;The flaw in this function is that it's returning a "handle" ? in this case, a pointer ? to information that should be hidden inside the String object on which the function is invoked. That handle gives callers unrestricted access to what the private field data points to.&lt;br /&gt;&lt;p&gt;Item 30: Avoid member functions that return non-const pointers or references to members less accessible than themselves.&lt;br /&gt;&lt;p&gt;Item 31: Never return a reference to a local object or to a dereferenced pointer initialized by new within the function.&lt;br /&gt;&lt;p&gt;In spite of the foregoing discussion, you may someday be faced with a situation in which, pressed to achieve performance constraints, you honestly need to write a member function that returns a reference or a pointer to a less-accessible member. At the same time, however, you won't want to sacrifice the access restrictions that private and protected afford you. In those cases, you can almost always achieve both goals by returning a pointer or a reference to a const object.&lt;br /&gt;&lt;h3&gt;Item 32: Postpone variable definitions as long as possible.&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;Not only should you postpone a variable's definition until right before you have to use the variable, you should try to postpone the definition until you have initialization arguments for it. By doing so, you avoid not only constructing and destructing unneeded objects, you also avoid pointless default constructions. Further, you help document the purpose of variables by initializing them in contexts in which their meaning is clear.&lt;br /&gt;&lt;p&gt;Item 33: Use inlining judiciously.&lt;br /&gt;&lt;p&gt;Item 34: Minimize compilation dependencies between files.&lt;br /&gt;&lt;p&gt;Item 35: Make sure public inheritance models "isa."&lt;br /&gt;&lt;p&gt;Item 36: Differentiate between inheritance of interface and inheritance of implementation.&lt;br /&gt;&lt;p&gt;Item 37: Never redefine an inherited nonvirtual function.&lt;br /&gt;&lt;p&gt;Item 38: Never redefine an inherited default parameter value.&lt;br /&gt;&lt;p&gt;Item 39: Avoid casts down the inheritance hierarchy.&lt;br /&gt;&lt;p&gt;Item 40: Model "has-a" or "is-implemented-in-terms-of" through layering.&lt;br /&gt;&lt;p&gt;Item 41: Differentiate between inheritance and templates.&lt;br /&gt;&lt;p&gt;Item 42: Use private inheritance judiciously.&lt;br /&gt;&lt;p&gt;Item 43: Use multiple inheritance judiciously.&lt;br /&gt;&lt;p&gt;Item 44: Say what you mean; understand what you're saying.&lt;br /&gt;&lt;p&gt;Item 45: Know what functions C++ silently writes and calls.&lt;br /&gt;&lt;p&gt;Item 46: Prefer compile-time and link-time errors to runtime errors.&lt;br /&gt;&lt;p&gt;Item 47: Ensure that non-local static objects are initialized before they're used.&lt;br /&gt;&lt;p&gt;Item 48: Pay attention to compiler warnings.&lt;br /&gt;&lt;p&gt;Item 49: Familiarize yourself with the standard library.&lt;br /&gt;&lt;p&gt;Item 50: Improve your understanding of C++.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-8521951497746845669?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8521951497746845669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8521951497746845669'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/c-effective-notes.html' title='C++ Effective notes'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/greeness/SNiCXwhnn1I/AAAAAAAAB0A/8dfr4rdeK7k/s72-c/image_thumb%5B2%5D.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-4232719643293663610</id><published>2008-09-21T22:24:00.001-07:00</published><updated>2008-09-21T22:24:17.386-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>Number Split</title><content type='html'>&lt;p&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=4451"&gt;NumberSplit &lt;/a&gt;&lt;/p&gt;  &lt;p&gt;By &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm242"&gt;Editorial&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;The first thing to notice here is that the numbers in every step become smaller. Let's take an example and say we have a five digit number of the form &lt;code&gt;abcde&lt;/code&gt; (&lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;, &lt;code&gt;d&lt;/code&gt; and &lt;code&gt;e&lt;/code&gt; represent the decimal digits of the number), which we split to produce the successor: &lt;code&gt;ab * c * de&lt;/code&gt;. Here it is always &lt;code&gt;c &amp;lt; 10&lt;/code&gt; and &lt;code&gt;de &amp;lt; 100&lt;/code&gt;, so for the successor we have: &lt;code&gt;ab * c * de &amp;lt; ab * 10 * 100 = ab000 ≤ abcde&lt;/code&gt;. Similar with any other numbers and splittings. &lt;/p&gt;  &lt;p&gt;Now we need a way to compute all possible successors, given a given number. For this we can use the following recursive pseudo-code: &lt;/p&gt;  &lt;pre&gt;generateSuccessors(int multiplier, int n) {&lt;br /&gt;    add (multiplier * n) to the set of successors&lt;br /&gt;    for (i = 10; i &amp;lt;= n; i *= 10) {&lt;br /&gt;       generateSuccessors(multiplier * (n / i), n % i);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We initialize the set of successors to an empty set, and call &lt;code&gt;generateSuccessors(1, n)&lt;/code&gt; (where &lt;code&gt;n&lt;/code&gt; is the number, for which we want to find the successors). Finally, we remove &lt;code&gt;n&lt;/code&gt; from the generated set (since this is not a successor of &lt;code&gt;n&lt;/code&gt; itself, we need to split the given number to at least two parts for a successor to be valid). &lt;/p&gt;&lt;br /&gt;&lt;p&gt;To compute the longest possible sequence, starting with the given &lt;code&gt;start&lt;/code&gt;, generate all successors of &lt;code&gt;start&lt;/code&gt; as described above, and for each &lt;code&gt;n&lt;/code&gt; in the successor set compute recursively &lt;code&gt;longestSequence(n)&lt;/code&gt;. The return value is the maximum of all computed values + 1 (if &lt;code&gt;start&lt;/code&gt; is a single digit number, the successors set will be empty, and we return 1). Note that this would not work if loops in the sequence were possible, but since each successor is smaller then the original number, this can not happen. In order to avoid a timeout, we need to memorize in a buffer all values already computed. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Alternatively, we can use dynamic programming, by initializing &lt;code&gt;longest[i] = 1&lt;/code&gt; for all single digit numbers &lt;code&gt;i&lt;/code&gt;, and computing &lt;code&gt;longest[i]&lt;/code&gt; from &lt;code&gt;i = 10&lt;/code&gt; up to &lt;code&gt;i = start&lt;/code&gt; by adding 1 to the maximum of &lt;code&gt;longest[j]&lt;/code&gt; for all &lt;code&gt;j&lt;/code&gt; in the successor set of &lt;code&gt;i&lt;/code&gt;. This works, since all successors of &lt;code&gt;i&lt;/code&gt; are smaller than &lt;code&gt;i&lt;/code&gt;. With this solution, we compute the longest sequence for more numbers than actually needed (many numbers between 1 and &lt;code&gt;start&lt;/code&gt; can not be reached from &lt;code&gt;start&lt;/code&gt;) but with the low constraints this solution was within the time limit. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;my dp code with memoization (note: topCoder does not have itoa)&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue"&gt;void&lt;/span&gt; itoa(&lt;span style="color: blue"&gt;int&lt;/span&gt; n, &lt;span style="color: blue"&gt;char&lt;/span&gt;* buff) {&lt;br /&gt;    sprintf(buff, &lt;span style="color: maroon"&gt;&amp;quot;%d&amp;quot;&lt;/span&gt;, n);&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: green"&gt;// memoization array&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; a[&lt;span style="color: maroon"&gt;999999&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; solve(&lt;span style="color: blue"&gt;string&lt;/span&gt; s) {&lt;br /&gt;    &lt;span style="color: blue"&gt;int&lt;/span&gt; ss = atoi(s.c_str());&lt;br /&gt;    &lt;span style="color: blue"&gt;if&lt;/span&gt;(a[ss] != -&lt;span style="color: maroon"&gt;1&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt; a[ss];&lt;br /&gt;    &lt;span style="color: blue"&gt;char&lt;/span&gt; buff[&lt;span style="color: maroon"&gt;10&lt;/span&gt;];&lt;br /&gt;    &lt;span style="color: blue"&gt;if&lt;/span&gt;(s.length() == &lt;span style="color: maroon"&gt;1&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: maroon"&gt;1&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: blue"&gt;int&lt;/span&gt; res = &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; i &amp;lt; s.length(); ++i) {&lt;br /&gt;        &lt;span style="color: green"&gt;// single split&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;int&lt;/span&gt; left  = atoi(s.substr(&lt;span style="color: maroon"&gt;0&lt;/span&gt;,i).c_str());&lt;br /&gt;        &lt;span style="color: blue"&gt;int&lt;/span&gt; right = atoi(s.substr(i).c_str());&lt;br /&gt;        itoa(left*right, buff);       &lt;br /&gt;        checkmax(res, &lt;span style="color: maroon"&gt;1&lt;/span&gt;+solve(&lt;span style="color: blue"&gt;string&lt;/span&gt;(buff)));&lt;br /&gt;        &lt;span style="color: blue"&gt;string&lt;/span&gt; rights = s.substr(i);&lt;br /&gt;        &lt;span style="color: blue"&gt;if&lt;/span&gt;(rights.length() &amp;lt;= &lt;span style="color: maroon"&gt;1&lt;/span&gt;) &lt;span style="color: blue"&gt;continue&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: green"&gt;// this part does double split&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; j = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; j &amp;lt; rights.length(); ++j) {&lt;br /&gt;            &lt;span style="color: blue"&gt;int&lt;/span&gt; lleft  = atoi(rights.substr(&lt;span style="color: maroon"&gt;0&lt;/span&gt;,j).c_str());&lt;br /&gt;            &lt;span style="color: blue"&gt;int&lt;/span&gt; lright = atoi(rights.substr(j).c_str());&lt;br /&gt;            itoa(left * lleft * lright, buff);&lt;br /&gt;            checkmax(res, &lt;span style="color: maroon"&gt;1&lt;/span&gt;+solve(&lt;span style="color: blue"&gt;string&lt;/span&gt;(buff)));&lt;br /&gt;        }           &lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue"&gt;return&lt;/span&gt; a[ss] = res;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; NumberSplit::longestSequence(&lt;span style="color: blue"&gt;int&lt;/span&gt; start) {&lt;br /&gt;    &lt;span style="color: blue"&gt;char&lt;/span&gt; buff[&lt;span style="color: maroon"&gt;10&lt;/span&gt;];&lt;br /&gt;    itoa(start,buff);&lt;br /&gt;    memset(a, -&lt;span style="color: maroon"&gt;1&lt;/span&gt;, &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(a));&lt;br /&gt;    &lt;span style="color: blue"&gt;string&lt;/span&gt; s(buff);&lt;br /&gt;    &lt;span style="color: blue"&gt;return&lt;/span&gt; solve(buff);&lt;br /&gt;}&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-4232719643293663610?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4232719643293663610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4232719643293663610'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/number-split.html' title='Number Split'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1519209416803258203</id><published>2008-09-21T20:44:00.001-07:00</published><updated>2008-10-01T04:43:22.076-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>Floyd-Warshall: All-Pairs Shortest Path</title><content type='html'>&lt;p&gt;By wiki, Floyd-Warshall is a &lt;a href="http://en.wikipedia.org/wiki/Graph_%28mathematics%29"&gt;graph&lt;/a&gt; analysis &lt;a href="http://en.wikipedia.org/wiki/Algorithm"&gt;algorithm&lt;/a&gt; for finding &lt;a href="http://en.wikipedia.org/wiki/Shortest_path_problem"&gt;shortest paths&lt;/a&gt; in a weighted, directed graph. A single execution of the algorithm will find the shortest paths between all pairs of vertices. The &lt;b&gt;Floyd–Warshall algorithm&lt;/b&gt; is an example of &lt;a href="http://en.wikipedia.org/wiki/Dynamic_programming"&gt;dynamic programming&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt; 1 /* Assume a function &lt;i&gt;edgeCost&lt;/i&gt;(i,j) which returns the cost of the edge from i to j&lt;br&gt;2    (infinity if there is none).&lt;br&gt;3    Also assume that &lt;b&gt;n&lt;/b&gt; is the number of vertices and &lt;i&gt;edgeCost&lt;/i&gt;(i,i)=0&lt;br&gt;4 */&lt;br&gt;5&lt;br&gt;6 &lt;b&gt;int&lt;/b&gt; path[][];&lt;br&gt;7 /* A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path&lt;br&gt;8    from i to j using intermediate values in (1..k-1).  Each path[i][j] is initialized to&lt;br&gt;9    &lt;i&gt;edgeCost&lt;/i&gt;(i,j).&lt;br&gt;10 */&lt;br&gt;11&lt;br&gt;12 &lt;b&gt;procedure&lt;/b&gt; &lt;i&gt;FloydWarshall&lt;/i&gt; ()&lt;br&gt;13    &lt;b&gt;for&lt;/b&gt; &lt;i&gt;k&lt;/i&gt;: = 0 &lt;b&gt;to&lt;/b&gt; &lt;i&gt;n&lt;/i&gt; − &lt;i&gt;1&lt;/i&gt;&lt;br&gt;14       &lt;b&gt;for each&lt;/b&gt; (&lt;i&gt;i&lt;/i&gt;,&lt;i&gt;j&lt;/i&gt;) &lt;b&gt;in&lt;/b&gt; (0..&lt;i&gt;n&lt;/i&gt; − 1)&lt;br&gt;15          path[i][j] = min ( path[i][j], path[i][k]+path[k][j] );&lt;/pre&gt;&lt;a name="Behaviour_with_negative_cycles"&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;&lt;/h4&gt;For numerically meaningful output, Floyd-Warshall assumes that there are no negative cycles (in fact, between any pair of vertices which form part of a negative cycle, the shortest path is not well-defined because the path can be infinitely small). Nevertheless, if there are negative cycles, Floyd–Warshall can be used to detect them. A negative cycle can be detected if the &lt;i&gt;path&lt;/i&gt; matrix contains a negative number along the diagonal. If path[i][i] is negative for some vertex i, then this vertex belongs to at least one negative cycle.&lt;br&gt;&lt;br /&gt;&lt;h4&gt;Applications:&lt;br&gt;&lt;/h4&gt;&lt;br /&gt;&lt;li&gt;Shortest paths in directed graphs (Floyd's algorithm).&lt;br /&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Transitive_closure"&gt;Transitive closure&lt;/a&gt; of directed graphs (Warshall's algorithm). In Warshall's original formulation of the algorithm, the graph is unweighted and represented by a Boolean adjacency matrix. Then the addition operation is replaced by &lt;a href="http://en.wikipedia.org/wiki/Logical_conjunction"&gt;logical conjunction&lt;/a&gt; (AND) and the minimum operation by &lt;a href="http://en.wikipedia.org/wiki/Logical_disjunction"&gt;logical disjunction&lt;/a&gt; (OR). &lt;br /&gt;&lt;li&gt;Optimal routing. In this application one is interested in finding the path with the maximum flow between two vertices. This means that, rather than taking minima as in the pseudocode above, one instead takes maxima. The edge weights represent fixed constraints on flow. Path weights represent bottlenecks; so the addition operation above is replaced by the minimum operation. &lt;br /&gt;&lt;li&gt;Testing whether an &lt;a href="http://en.wikipedia.org/wiki/Undirected_graph"&gt;undirected graph&lt;/a&gt; is &lt;a href="http://en.wikipedia.org/wiki/Bipartite_graph"&gt;bipartite&lt;/a&gt; &lt;br /&gt;&lt;li&gt;Minmax / Maxmin Distance&lt;br&gt;&lt;br /&gt;&lt;p&gt;Shortest Path Problems:&lt;br&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; Floyd_Warshall (&lt;span style="color: blue"&gt;int&lt;/span&gt; n) {&lt;br&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; k = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; k &amp;lt; n; ++k)&lt;br&gt; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; i &amp;lt; n; ++i)&lt;br&gt;   &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; j = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; j &amp;lt; n; ++ j)&lt;br&gt;     G[i][j] = min(G[i][j], G[i][k] + G[k][j]);&lt;br&gt;}     &lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=3529"&gt;MoneyExchange&lt;/a&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 104: &lt;a href="http://online-judge.uva.es/p/v1/104.html"&gt;Arbitrage&lt;/a&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 436: &lt;a href="http://online-judge.uva.es/p/v4/436.html"&gt;Arbitrage (II)&lt;/a&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 423: &lt;a href="http://online-judge.uva.es/p/v4/423.html"&gt;MPI Maelstrom&lt;/a&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 567: &lt;a href="http://online-judge.uva.es/p/v5/567.html"&gt;Risk&lt;/a&gt;&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Transitive Closure/Hull&lt;br&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; k = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; k &amp;lt; N; ++k)&lt;br&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; i &amp;lt; N; ++i)&lt;br&gt; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; j = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; j &amp;lt; N; ++j)&lt;br&gt;   G[i][j] = G[i][j] || (G[i][k] &amp;amp;&amp;amp; G[k][j]);&lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 334: &lt;a href="http://online-judge.uva.es/p/v3/334.html"&gt;Identifying concurrent events&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Minmax/ Maxmin distance&lt;/p&gt;&lt;span style="color: blue"&gt;void&lt;/span&gt; minmax(&lt;span style="color: blue"&gt;int&lt;/span&gt; n) {&lt;br&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;div style="font-family: courier new"&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; k = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; k &amp;lt; n; ++k)&lt;br&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; i &amp;lt; n; ++i)&lt;br&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; j = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; j &amp;lt; n; ++j)&lt;br&gt;G[i][j] = min(G[i][j], max(G[i][k], G[k][j]));&lt;br&gt;}&lt;/div&gt;&lt;br&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;div style="font-family: courier new"&gt;&lt;span style="color: blue"&gt;void&lt;/span&gt; maxmin(&lt;span style="color: blue"&gt;int&lt;/span&gt; n) {&lt;br&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; k = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; k &amp;lt; n; ++k)&lt;br&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; i &amp;lt; n; ++i)&lt;br&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; j = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; j &amp;lt; n; ++j) &lt;br&gt;G[i][j] = max(G[i][j], min(G[i][k], G[k][j]));&lt;br&gt;}&lt;/div&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 534: &lt;a href="http://online-judge.uva.es/p/v5/534.html"&gt;Frogger&lt;/a&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 10048: &lt;a href="http://acm.uva.es/p/v100/10048.html"&gt;Audiophobia&lt;/a&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 544: &lt;a href="http://online-judge.uva.es/p/v5/544.html"&gt;Heavy Cargo&lt;/a&gt;&lt;br&gt;&lt;br /&gt;&lt;li&gt;UVa 10099: &lt;a href="http://acm.uva.es/p/v100/10099.html"&gt;The Tourist Guide&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;/li&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1519209416803258203?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1519209416803258203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1519209416803258203'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/floyd-warshall-all-pairs-shortest-path.html' title='Floyd-Warshall: All-Pairs Shortest Path'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-3263199445492251871</id><published>2008-09-21T13:10:00.001-07:00</published><updated>2008-10-08T21:28:20.329-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>Subset Sum Problem</title><content type='html'>&lt;p&gt;The problem is this: given a set of integers, does the sum of some non-empty subset equal exactly zero?The problem is NP-Complete. &lt;a href="http://en.wikipedia.org/wiki/Subset_sum_problem#Pseudo-polynomial_time_dynamic_programming_solution"&gt;wiki&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;An equivalent problem is this: given a set of integers and an integer &lt;i&gt;s&lt;/i&gt;, does any non-empty subset sum to &lt;i&gt;s&lt;/i&gt;? Subset sum can also be thought of as a special case of the &lt;a href="http://en.wikipedia.org/wiki/Knapsack_problem"&gt;knapsack problem&lt;/a&gt;. One interesting special case of subset sum is the &lt;a href="http://en.wikipedia.org/wiki/Partition_problem"&gt;partition problem&lt;/a&gt;, in which &lt;i&gt;s&lt;/i&gt; is half of the sum of all elements in the set.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;b&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=3114&amp;amp;rd=5865" name="3114"&gt;PayBill&lt;/a&gt; &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm219"&gt;Editorial&lt;/a&gt;&lt;/b&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;There are two basic approaches to this problem. The first, which inevitably fails due to timeout on larger test cases, is to try obtain the sum by either including or excluding the first element, and then calling itself recursively with the remainder of the set. Unfortunately, with the maximum 50 people, this is over 1 quadrillion operations to perform.&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;Instead, a more clever, dynamic programming approach needs to be used. Since each item can only be up to 10,000, we know that the sum cannot be more than 500,000. So, we simply need a boolean array of 500,000 elements, where the i-th element represents whether or not we can reach the total i with some subset of the original values. In code it looks something like this:&lt;/p&gt;&lt;pre&gt;boolean[] canTotal = new boolean[500001];&lt;br&gt;canTotal[0] = true;&lt;br&gt;for (int i = 0; i &amp;lt; meals.length; i++)&lt;br&gt;  for (int j = totalMoney; j &amp;gt;= meals[i]; j--)&lt;br&gt;     if (canTotal[j - meals[i]]) canTotal[j] = true;&lt;br&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=2947"&gt;LoadBalancing&lt;/a&gt; &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm209"&gt;Editorial&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;int minTime(vector&amp;lt;int&amp;gt; chunkSizes)&lt;br&gt;{&lt;br&gt;   vector&amp;lt;int&amp;gt; dp(204801, 0);&lt;br&gt;   dp[0] = 1;&lt;br&gt;   int total = 0;&lt;br&gt;   for (int i=0; i&amp;lt;(int)chunkSizes.size(); i++)&lt;br&gt;   {&lt;br&gt;       total += chunkSizes[i]/1024;&lt;br&gt;       for (int j=204800; j&amp;gt;=0; j--)&lt;br&gt;           if (dp[j] == 1)&lt;br&gt;               dp[j+chunkSizes[i]/1024] = 1;&lt;br&gt;   }&lt;br&gt;   for (int i=(total+1)/2; true; i++)&lt;br&gt;       if (dp[i] == 1)&lt;br&gt;           return 1024 * i;&lt;br&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;UVa 562&lt;/strong&gt;: &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;category=7&amp;amp;page=show_problem&amp;amp;problem=503"&gt;Dividing Coins&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;跟上面一题如出一辙，就是平分问题。这里用了bitvector &lt;/p&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; MAX = 50000;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N = 1563;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; a[N+1];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; coin[101];&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ndata;&lt;br /&gt;    scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;ndata);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(ndata--) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n; &lt;br /&gt;        scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;n);&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;            scanf("&lt;span style="color: #8b0000"&gt;%d &lt;/span&gt;", &amp;amp;coin[i]);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; total = std::accumulate(coin, coin+n, 0);&lt;br /&gt;&lt;br /&gt;        memset(a, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)*(total&amp;gt;&amp;gt;SHIFT));&lt;br /&gt;        SET(a, 0);&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = total; j &amp;gt;= 0; --j)&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(TEST(a, j))&lt;br /&gt;                    SET(a, j+coin[i]);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = (total+1)/2; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(TEST(a, i)) {&lt;br /&gt;                printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", abs(2*i-total));&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;UVa 11517&lt;/strong&gt; &lt;a href="http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&amp;amp;page=show_problem&amp;amp;problem=2512"&gt;Exact Change&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;这道要多记一个coin的数目，不能用bitvector了&lt;/p&gt;&lt;pre&gt;        a[0] = 1;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = max-1; j &amp;gt;= 0; --j)&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(a[j]) {&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; t = j+ bill[i];&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(t &amp;gt; max) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(a[t] != 0)&lt;br /&gt;                        a[t] = a[t] &amp;lt; a[j]+1 ? a[t]: a[j]+1;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;br /&gt;                        a[t] = a[j]+1;&lt;br /&gt;                }&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = price; i &amp;lt;= MAX; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(a[i]) {&lt;br /&gt;                printf("&lt;span style="color: #8b0000"&gt;%d %d\n&lt;/span&gt;", i, a[i]-1);&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-3263199445492251871?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3263199445492251871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3263199445492251871'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/subset-sum-problem.html' title='Subset Sum Problem'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-3757767669434256449</id><published>2008-09-20T21:35:00.000-07:00</published><updated>2008-09-23T20:02:41.172-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>memo[i][j] = min ( memo[i][k] + memo[k+1][j] )</title><content type='html'>用类似这一recurrence的题非常多，在这汇总一下 &lt;br&gt; &lt;ul&gt; &lt;li&gt;topCoder: &lt;a class="statText" href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=2829"&gt;QuickSums &lt;/a&gt; &lt;li&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=1861"&gt;ShortPalindromes &lt;/a&gt; &lt;li&gt;topCoder: &lt;a class="statText" href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=3515"&gt;TreePlanting &lt;/a&gt; &lt;li&gt;topCoder: &lt;strong&gt;&lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=8692&amp;amp;rd=12183" name="8692"&gt;SentenceDecomposition&lt;/a&gt;&lt;/strong&gt; &lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;ul&gt;&lt;/ul&gt;&lt;strong&gt;&lt;span style="font-size: 130%"&gt;&lt;/span&gt;&lt;/strong&gt; &lt;h3&gt;topCoder: &lt;a class="statText" href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=2829"&gt;QuickSums&lt;/a&gt;&lt;br&gt;&lt;/h3&gt;&lt;pre&gt;INPUT: i, j, sum&lt;br&gt;for all  i &amp;lt;= k &amp;lt;= j   take out substring(i,k) from sum   try d[k+1][j] = solve(substring(k+1,j), sum - substring(i,k)); end for d[i][j] = min (1+d[k+1][j])         k=i...j&lt;/pre&gt;&lt;br&gt;边缘情况注意一下，如果d[i][j]整体已经等于sum，直接返回，不用1+res&lt;br&gt;&lt;br&gt;&lt;pre&gt;&lt;span style="color: blue"&gt;#define&lt;/span&gt; INF &lt;span style="color: maroon"&gt;999999999&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; memo[&lt;span style="color: maroon"&gt;12&lt;/span&gt;][&lt;span style="color: maroon"&gt;12&lt;/span&gt;][&lt;span style="color: maroon"&gt;102&lt;/span&gt;];&lt;br&gt;&lt;span style="color: blue"&gt;void&lt;/span&gt; checkmin(&lt;span style="color: blue"&gt;int&lt;/span&gt; &amp;amp;a, &lt;span style="color: blue"&gt;int&lt;/span&gt; b) {&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(b &amp;lt; a) a = b;&lt;br&gt;}&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; solve(&lt;span style="color: blue"&gt;string&lt;/span&gt; numbers, &lt;span style="color: blue"&gt;int&lt;/span&gt; i, &lt;span style="color: blue"&gt;int&lt;/span&gt; j, &lt;span style="color: blue"&gt;int&lt;/span&gt; s) {&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(memo[i][j][s] &amp;gt;= &lt;span style="color: maroon"&gt;0&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][s];&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(i == j) {&lt;br&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt; (numbers[i]-&lt;span style="color: maroon"&gt;'0'&lt;/span&gt; == s) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][s] = &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt;      &lt;span style="color: blue"&gt;else&lt;/span&gt; &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][s] = INF;&lt;br&gt;  }&lt;br&gt;  &lt;span style="color: green"&gt;// the whole word match! &lt;/span&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(atoi(numbers.substr(i, j-i+&lt;span style="color: maroon"&gt;1&lt;/span&gt;).c_str()) == s) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][s] = &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt;  &lt;span style="color: blue"&gt;int&lt;/span&gt; res = INF;&lt;br&gt;  &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; k = i; k &amp;lt; j; ++k) {&lt;br&gt;      &lt;span style="color: blue"&gt;int&lt;/span&gt; left  = atoi(numbers.substr(i,k-i+&lt;span style="color: maroon"&gt;1&lt;/span&gt;).c_str());&lt;br&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt;(left &amp;lt;= s){&lt;br&gt;           &lt;span style="color: green"&gt;//cout &amp;lt;&amp;lt; numbers.substr(k+1, j-k+1) &amp;lt;&amp;lt; "-&amp;gt;" &amp;lt;&amp;lt; s-left &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br&gt;           &lt;span style="color: blue"&gt;int&lt;/span&gt; sol = &lt;span style="color: maroon"&gt;1&lt;/span&gt;+solve(numbers, k+&lt;span style="color: maroon"&gt;1&lt;/span&gt;, j, s-left);&lt;br&gt;           &lt;span style="color: green"&gt;//cout &amp;lt;&amp;lt; numbers.substr(k+1, j-k+1) &amp;lt;&amp;lt; " (" &amp;lt;&amp;lt; sol &amp;lt;&amp;lt;")" &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br&gt;           checkmin(res, sol);&lt;br&gt;      }&lt;br&gt;  }&lt;br&gt;  &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][s] = res;&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; QuickSums::minSums(&lt;span style="color: blue"&gt;string&lt;/span&gt; numbers, &lt;span style="color: blue"&gt;int&lt;/span&gt; sum) {&lt;br&gt;  memset(memo, -&lt;span style="color: maroon"&gt;1&lt;/span&gt;, &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(memo));&lt;br&gt;  &lt;span style="color: blue"&gt;int&lt;/span&gt; res = solve(numbers, &lt;span style="color: maroon"&gt;0&lt;/span&gt;, numbers.length()-&lt;span style="color: maroon"&gt;1&lt;/span&gt;, sum);&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(res == INF) &lt;span style="color: blue"&gt;return&lt;/span&gt; -&lt;span style="color: maroon"&gt;1&lt;/span&gt;;&lt;br&gt;  &lt;span style="color: blue"&gt;return&lt;/span&gt; res;&lt;br&gt;}&lt;/pre&gt;&lt;br&gt;&lt;br /&gt;&lt;h3&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=1861"&gt;ShortPalindromes&lt;/a&gt;&lt;br&gt;&lt;/h3&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;“ shortest(base)&lt;br&gt;   if base is already a palindrome then&lt;br&gt;       return base&lt;br&gt;   if base has the form A...A then&lt;br&gt;       return A + shortest(...) + A&lt;br&gt;   if base has the form A...B then&lt;br&gt;       return min(A + shortest(...B) + A,&lt;br&gt;                  B + shortest(A...) + B)&lt;/pre&gt;&lt;pre&gt;”&lt;br&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;span style="color: blue"&gt;string&lt;/span&gt; memo[&lt;span style="color: maroon"&gt;26&lt;/span&gt;][&lt;span style="color: maroon"&gt;26&lt;/span&gt;];&lt;br&gt;&lt;span style="color: blue"&gt;string&lt;/span&gt; solve(&lt;span style="color: blue"&gt;string&lt;/span&gt; base, &lt;span style="color: blue"&gt;int&lt;/span&gt; i, &lt;span style="color: blue"&gt;int&lt;/span&gt; j) {&lt;br&gt;  &lt;span style="color: green"&gt;//cout &amp;lt;&amp;lt; base.substr(i,j-i+1) &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(i&amp;gt;j) &lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt;(&lt;span style="color: maroon"&gt;""&lt;/span&gt;);&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(i == j) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j]=base[i];&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(memo[i][j] != &lt;span style="color: maroon"&gt;""&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j];&lt;br&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;string&lt;/span&gt; res;&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(base[i] == base[j]) {&lt;br&gt;      res = base[i] + solve(base, i+&lt;span style="color: maroon"&gt;1&lt;/span&gt;, j-&lt;span style="color: maroon"&gt;1&lt;/span&gt;)+base[i];&lt;br&gt;      &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j]=res;&lt;br&gt;  }&lt;br&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;string&lt;/span&gt; pre = base[j] + solve(base, i, j-&lt;span style="color: maroon"&gt;1&lt;/span&gt;) + base[j];&lt;br&gt;  &lt;span style="color: blue"&gt;string&lt;/span&gt; suf = base[i] + solve(base, i+&lt;span style="color: maroon"&gt;1&lt;/span&gt;, j) + base[i];&lt;br&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(pre.length() != suf.length()) {&lt;br&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt;(pre.length() &amp;lt; suf.length()) res = pre;&lt;br&gt;      &lt;span style="color: blue"&gt;else&lt;/span&gt; res = suf;&lt;br&gt;  }&lt;br&gt;  &lt;span style="color: blue"&gt;else&lt;/span&gt; {&lt;br&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt;(pre &amp;lt; suf) res = pre;&lt;br&gt;      &lt;span style="color: blue"&gt;else&lt;/span&gt; res = suf;&lt;br&gt;  }&lt;br&gt;  &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j]=res;&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;string&lt;/span&gt; ShortPalindromes::shortest(&lt;span style="color: blue"&gt;string&lt;/span&gt; base) {&lt;br&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;int&lt;/span&gt; L = base.length();&lt;br&gt;  &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; i &amp;lt; L; ++i)&lt;br&gt;      &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; j = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; j &amp;lt; L; ++j)&lt;br&gt;          memo[i][j]=&lt;span style="color: maroon"&gt;""&lt;/span&gt;;&lt;br&gt;  &lt;span style="color: blue"&gt;return&lt;/span&gt; solve(base, &lt;span style="color: maroon"&gt;0&lt;/span&gt;, base.length()-&lt;span style="color: maroon"&gt;1&lt;/span&gt;);&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;topCoder: &lt;a class="statText" href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=3515"&gt;TreePlanting&lt;/a&gt;&lt;br&gt;&lt;/h3&gt;&lt;br&gt;&lt;pre&gt;&lt;span style="color: blue"&gt;long&lt;/span&gt; &lt;span style="color: blue"&gt;long&lt;/span&gt; memo[&lt;span style="color: maroon"&gt;62&lt;/span&gt;][&lt;span style="color: maroon"&gt;62&lt;/span&gt;][&lt;span style="color: maroon"&gt;62&lt;/span&gt;];&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; N;&lt;br&gt;&lt;span style="color: blue"&gt;long&lt;/span&gt; &lt;span style="color: blue"&gt;long&lt;/span&gt; solve(&lt;span style="color: blue"&gt;long&lt;/span&gt; &lt;span style="color: blue"&gt;long&lt;/span&gt; status, &lt;span style="color: blue"&gt;int&lt;/span&gt; i, &lt;span style="color: blue"&gt;int&lt;/span&gt; j, &lt;span style="color: blue"&gt;int&lt;/span&gt; f) {&lt;br&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(memo[i][j][f] != -&lt;span style="color: maroon"&gt;1LL&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][f];&lt;br&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(f == &lt;span style="color: maroon"&gt;0&lt;/span&gt; || (i == j &amp;amp;&amp;amp; f == &lt;span style="color: maroon"&gt;1&lt;/span&gt;)) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][f] = &lt;span style="color: maroon"&gt;1LL&lt;/span&gt;;&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(i &amp;gt; j) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][f] = &lt;span style="color: maroon"&gt;0LL&lt;/span&gt;;&lt;br&gt;  &lt;span style="color: blue"&gt;if&lt;/span&gt;(i == j &amp;amp;&amp;amp; f &amp;gt; &lt;span style="color: maroon"&gt;1&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][f] = &lt;span style="color: maroon"&gt;0LL&lt;/span&gt;;&lt;br&gt;&lt;br&gt;  &lt;span style="color: blue"&gt;long&lt;/span&gt; &lt;span style="color: blue"&gt;long&lt;/span&gt; res = &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt;  &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; k = i; k &amp;lt;= j; ++k) &lt;span style="color: blue"&gt;if&lt;/span&gt;(status &amp;amp; &lt;span style="color: maroon"&gt;1LL&lt;/span&gt;&amp;lt;&amp;lt;k) {&lt;br&gt;&lt;br&gt;      res += solve(status ^ (&lt;span style="color: maroon"&gt;1LL&lt;/span&gt;&amp;lt;&amp;lt;k), k+&lt;span style="color: maroon"&gt;2&lt;/span&gt;, j, f-&lt;span style="color: maroon"&gt;1&lt;/span&gt;);&lt;br&gt;  }&lt;br&gt;  &lt;span style="color: blue"&gt;return&lt;/span&gt; memo[i][j][f] = res;&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;long&lt;/span&gt; &lt;span style="color: blue"&gt;long&lt;/span&gt; TreePlanting::countArrangements(&lt;span style="color: blue"&gt;int&lt;/span&gt; total, &lt;span style="color: blue"&gt;int&lt;/span&gt; fancy) {&lt;br&gt;  memset(memo, -&lt;span style="color: maroon"&gt;1&lt;/span&gt;, &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(memo));&lt;br&gt;  N = total;&lt;br&gt;  &lt;span style="color: blue"&gt;long&lt;/span&gt; &lt;span style="color: blue"&gt;long&lt;/span&gt; status = (&lt;span style="color: maroon"&gt;1LL&lt;/span&gt;&amp;lt;&amp;lt;total)-&lt;span style="color: maroon"&gt;1&lt;/span&gt;;&lt;br&gt;  &lt;span style="color: blue"&gt;return&lt;/span&gt; solve(status, &lt;span style="color: maroon"&gt;0&lt;/span&gt;, total-&lt;span style="color: maroon"&gt;1&lt;/span&gt;, fancy);&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;&lt;pre&gt;&lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm227"&gt;Editorial&lt;/a&gt; solution:&lt;br&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Here, we need to get a little creative to come up with a workable solution. Consider placing &lt;i&gt;f&lt;/i&gt; fancy trees along a total of &lt;i&gt;n&lt;/i&gt; locations, so that no two are adjacent. Call our function, C, the number of ways to do this. At our first location, we can either plant a fancy tree, or not plant a fancy tree. If we plant a fancy tree, then we can't plant a fancy tree in the second spot, and hence will have &lt;i&gt;n&lt;/i&gt;-2 locations in which to plant the remaining &lt;i&gt;f&lt;/i&gt;-1 fancy trees. If we don't plant a fancy tree in the first spot, then we have &lt;i&gt;n&lt;/i&gt;-1 locations in which to place all &lt;i&gt;f&lt;/i&gt; fancy trees. This gives us our recursive formula, &lt;i&gt;C(n, f) = C(n - 2, f - 1) + C(n - 1, f)&lt;/i&gt;. Our starting values are of course, &lt;i&gt;C&lt;/i&gt;(1, 1) = 1, and &lt;i&gt;C&lt;/i&gt;(0, 0) = 1.&lt;/p&gt;However, with the problem constraints as they are, a simple recursive function by itself is not sufficient. We either need to implement memoization, whereby we store the values of previous recursive calls, to avoid recalculating them repeatedly, or we can use dynamic programming, as shown here:&lt;br&gt;&lt;br&gt;&lt;pre&gt;public long countArrangements(int total, int fancy) {&lt;br&gt;  long[][] count = new long[total + 1][fancy + 1];&lt;br&gt;  count[0][0] = 1;&lt;br&gt;  count[1][1] = 1;&lt;br&gt;  for (int i = 0; i &amp;lt; = total; i++)&lt;br&gt;     for (int j = 0; j &amp;lt; = fancy; j++) {&lt;br&gt;        if (i &amp;gt; 0)&lt;br&gt;           count[i][j] += count[i - 1][j];&lt;br&gt;        if (i &amp;gt; 1 &amp;amp;&amp;amp; j &amp;gt; 0)&lt;br&gt;           count[i][j] += count[i - 2][j - 1];&lt;br&gt;     };&lt;br&gt;  return count[total][fancy];&lt;br&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;topCoder: &lt;strong&gt;&lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=8692&amp;amp;rd=12183" name="8692"&gt;SentenceDecomposition&lt;/a&gt;&lt;/strong&gt;&lt;/h3&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; diff(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;amp; a, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;amp; b) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cost = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0;i &amp;lt; a.length(); ++i)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(a[i]!=b[i]) cost ++;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; cost;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; match(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;amp; aa, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; &amp;amp;bb) {&lt;br /&gt;    sort(ALL(aa));&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; aa==bb;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; memo[52];&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;//dict is a copy of validWords&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;//sort_dict is a copy of dict, but each row is sorted&lt;/span&gt;&lt;br /&gt;vector&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; dict, sort_dict;&lt;br /&gt;#define INF 999999999&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; solve(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; &amp;amp;s) {&lt;br /&gt;    &lt;span style="color: #008000"&gt;//cout &amp;lt;&amp;lt; s.substr(i) &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(memo[i] != -1) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; memo[i];&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(i == s.length()) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; memo[i] = 0;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(i &amp;gt; s.length()) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; memo[i]=INF;&lt;br /&gt;        &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; found  = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; mincost = INF;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = 0; k &amp;lt; dict.size(); ++k) {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; len = dict[k].length();&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(!match(s.substr(i, len), sort_dict[k])) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ret = 0;&lt;br /&gt;        ret = solve(i+len, s); &lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(ret == INF) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {&lt;br /&gt;            found = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;            ret += diff(s.substr(i, len), dict[k]);&lt;br /&gt;        }&lt;br /&gt;        mincost = min(mincost, ret);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(found) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; memo[i] = mincost;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; memo[i] = INF;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; SentenceDecomposition::decompose(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; sentence, vector &amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; validWords) {&lt;br /&gt;    sort_dict = dict = validWords;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; sort_dict.size(); ++i)&lt;br /&gt;        sort(ALL(sort_dict[i]));&lt;br /&gt;    &lt;br /&gt;    memset(memo, -1, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(memo));&lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; res = solve(0, sentence);    &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(res == INF) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; -1;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; res;&lt;br /&gt;}&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-3757767669434256449?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3757767669434256449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/3757767669434256449'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/memoij-min-memoik-memok1j.html' title='memo[i][j] = min ( memo[i][k] + memo[k+1][j] )'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-1416064208897485514</id><published>2008-09-19T17:54:00.000-07:00</published><updated>2008-09-21T20:06:55.943-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>Longest Increasing/Decreasing Subsequence</title><content type='html'>&lt;p&gt;A lot of related problems:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=1784"&gt;thePriceIsRight&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;pm=3937"&gt;autoMarket&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;pm=2240"&gt;books&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UVa 111: &lt;a href="http://acm.uva.es/p/v1/111.html"&gt;history grading&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UVa 231: &lt;a href="http://acm.uva.es/p/v2/231.html"&gt;testing the catcher&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UVa 497: &lt;a href="http://acm.uva.es/p/v4/497.html"&gt;strategic Defense Initiative&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UVa 10051: &lt;a href="http://acm.uva.es/p/v100/10051.html"&gt;Tower of Cubes&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UVa 10131: &lt;a href="http://acm.uva.es/p/v101/10131.html"&gt;Is Bigger Smarter&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Hoj: online tutorial problem 117, Intercept Missiles&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;two basic dp algorithms&lt;/p&gt;e.g., &lt;pre&gt;sequence: 1,6,2,3,5,4,7&lt;br /&gt;algorithm 1: O(N^2)&lt;br /&gt;a    1  2  3  4  5  6  7&lt;br /&gt;---------------------------&lt;br /&gt; 1  6  2  3  5  4  7&lt;br /&gt;---------------------------&lt;br /&gt;0|  1  1  1  1  1  1  1&lt;br /&gt;1| (1) 2  2  2  2  2  2&lt;br /&gt;2|  1 (2) 2  2  2  2  2&lt;br /&gt;3|  1  2 (2) 3  3  3  3&lt;br /&gt;4|  1  2  2 (3) 4  4  4 &lt;br /&gt;5|  1  2  2  3 (4) 4  5&lt;br /&gt;6|  1  2  2  3  4 (4) 5 &amp;lt;-            &lt;br /&gt;&lt;br /&gt;algorithm 2: O(NlogN)&lt;br /&gt;a    1  2  3  4  5  6  7&lt;br /&gt;---------------------------&lt;br /&gt; 1  6  2  3  5  4  7&lt;br /&gt;---------------------------&lt;br /&gt;0|  1&lt;br /&gt;1|  1  6&lt;br /&gt;2|  1  2&lt;br /&gt;3|  1  2  3&lt;br /&gt;4|  1  2  3  5&lt;br /&gt;5|  1  2  3  4&lt;br /&gt;6|  1  2  3  4  7 &amp;lt;-&lt;/pre&gt;&lt;pre&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=1784"&gt;thePriceIsRight&lt;/a&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span style="color:Green;"&gt;// longest increasing sequence (O(N^2)) &lt;/span&gt;&lt;br /&gt;vector&amp;lt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&amp;gt; lis (vector&amp;lt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&amp;gt; prices) {&lt;br /&gt; vector&amp;lt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&amp;gt; len(prices.size(), &lt;span style="color:Maroon;"&gt;1&lt;/span&gt;); &lt;span style="color:Green;"&gt;//length of the longest inc sequence up to i &lt;/span&gt;&lt;br /&gt; vector&amp;lt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&amp;gt; ways(prices.size(), &lt;span style="color:Maroon;"&gt;1&lt;/span&gt;); &lt;span style="color:Green;"&gt;//how many ways of the lcs up to i &lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:Blue;"&gt;for&lt;/span&gt;(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = &lt;span style="color:Maroon;"&gt;0&lt;/span&gt;; i &amp;lt; prices.size()-&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;; ++i) {&lt;br /&gt;     &lt;span style="color:Blue;"&gt;for&lt;/span&gt;(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; j = i+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;; j &amp;lt; prices.size(); ++j)&lt;br /&gt;         &lt;span style="color:Blue;"&gt;if&lt;/span&gt;(prices[j] &amp;gt; prices[i]) {&lt;br /&gt;             &lt;span style="color:Blue;"&gt;if&lt;/span&gt;(len[j] &amp;lt; len[i] + &lt;span style="color:Maroon;"&gt;1&lt;/span&gt;) {&lt;br /&gt;                 len[j] = len[i] + &lt;span style="color:Maroon;"&gt;1&lt;/span&gt;;&lt;br /&gt;                 ways[j] = ways[i];&lt;br /&gt;             }&lt;br /&gt;             &lt;span style="color:Blue;"&gt;else&lt;/span&gt; &lt;span style="color:Blue;"&gt;if&lt;/span&gt;(len[j] == len[i]+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;)&lt;br /&gt;                 ways[j]+= ways[i];&lt;br /&gt;         }&lt;br /&gt; }&lt;br /&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; maxv = *max_element(len.begin(), len.end());&lt;br /&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; nways = &lt;span style="color:Maroon;"&gt;0&lt;/span&gt;;&lt;br /&gt; &lt;span style="color:Blue;"&gt;for&lt;/span&gt;(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = &lt;span style="color:Maroon;"&gt;0&lt;/span&gt;; i &amp;lt; len.size(); ++i)&lt;br /&gt;     &lt;span style="color:Blue;"&gt;if&lt;/span&gt;(len[i] == maxv) nways += ways[i];&lt;br /&gt; vector&amp;lt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&amp;gt; res;&lt;br /&gt; res.push_back(maxv), res.push_back(nways);&lt;br /&gt; &lt;span style="color:Blue;"&gt;return&lt;/span&gt; res;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div style="font-family: courier new;"&gt; &lt;/div&gt;&lt;pre&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=2240"&gt;Books&lt;/a&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=' color: Green;'&gt;// binary search &lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;template&lt;/span&gt;&amp;lt;&lt;span style=' color: Blue;'&gt;typename&lt;/span&gt; T1, &lt;span style=' color: Blue;'&gt;typename&lt;/span&gt; T2&amp;gt; &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; bsearch(T1 &amp;amp;A, T2 target) {&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; u = &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;; &lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; v = A.size()-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;while&lt;/span&gt;(u &amp;lt; v) {&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; c = (u + v) / &lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;;&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (target &amp;gt; A[c]) u=c+&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; &lt;br /&gt;        &lt;span style=' color: Blue;'&gt;else&lt;/span&gt; v=c;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; u;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Green;'&gt;// longest non-decreasing sequence &lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;template&lt;/span&gt;&amp;lt;&lt;span style=' color: Blue;'&gt;typename&lt;/span&gt; T&amp;gt; &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; lis (vector&amp;lt;T&amp;gt; &amp;amp;seq) {&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(seq.empty()) &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;;&lt;br /&gt;    vector&amp;lt;T&amp;gt; A;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; n = seq.size();&lt;br /&gt;    A.push_back(seq[&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;]);&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; u, v;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; i = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; i &amp;lt; n; ++i) {&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(seq[i] &amp;gt;= A.back()) {&lt;br /&gt;            A.push_back(seq[i]);&lt;br /&gt;            &lt;span style=' color: Blue;'&gt;continue&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; u = bsearch(A, seq[i]);&lt;br /&gt;        &lt;span style=' color: Green;'&gt;//important !!! when compute non-increasing or non-decreasing seq&lt;/span&gt;&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(A[u] == seq[i]) A[u+&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;] = seq[i];&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;else&lt;/span&gt; A[u] = seq[i];&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; A.size();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; Books::sortMoves(vector &amp;lt;&lt;span style=' color: Blue;'&gt;string&lt;/span&gt;&amp;gt; titles) {&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; books.size()-lis(titles);&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-1416064208897485514?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1416064208897485514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/1416064208897485514'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/longest-increasingdecreasing.html' title='Longest Increasing/Decreasing Subsequence'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-7711849327114131657</id><published>2008-09-19T17:32:00.000-07:00</published><updated>2008-09-19T17:46:16.962-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>WordParts</title><content type='html'>&lt;p&gt;TopCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=1361"&gt;WordParts&lt;/a&gt; –&amp;gt; &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm156"&gt;Editorial&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;prefix, suffix&lt;br /&gt;&lt;/li&gt;&lt;li&gt;memoization&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;d[i][j] = min(d[i][k] + d[k+1][j])&lt;br /&gt;          k --- substring(i,k) exists in the prefix/suffix array&lt;/pre&gt;&lt;pre&gt;set&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt; dict;&lt;br /&gt;&lt;span style="color:blue;"&gt;#define&lt;/span&gt; INF &lt;span style="color:maroon;"&gt;999999999&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt; memo[&lt;span style="color:maroon;"&gt;51&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; checkmin(&lt;span style="color:blue;"&gt;int&lt;/span&gt; &amp;amp;a, &lt;span style="color:blue;"&gt;int&lt;/span&gt; b) {&lt;br /&gt;   &lt;span style="color:blue;"&gt;if&lt;/span&gt; (b &amp;lt; a) a = b;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt; solve(&lt;span style="color:blue;"&gt;string&lt;/span&gt; &amp;amp;compound, &lt;span style="color:blue;"&gt;int&lt;/span&gt; cpos) {&lt;br /&gt;   &lt;span style="color:green;"&gt;//cout &amp;lt;&amp;lt; compound.substr(cpos) &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; cpos &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:blue;"&gt;if&lt;/span&gt;(memo[cpos] &amp;gt;= &lt;span style="color:maroon;"&gt;0&lt;/span&gt;) &lt;span style="color:blue;"&gt;return&lt;/span&gt; memo[cpos];&lt;br /&gt;   &lt;span style="color:blue;"&gt;if&lt;/span&gt;(cpos == compound.length()) &lt;span style="color:blue;"&gt;return&lt;/span&gt; memo[cpos] = &lt;span style="color:maroon;"&gt;0&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;   &lt;span style="color:blue;"&gt;int&lt;/span&gt; res = INF;&lt;br /&gt;   &lt;span style="color:blue;"&gt;int&lt;/span&gt; maxlen = compound.length() - cpos;&lt;br /&gt;&lt;br /&gt;   &lt;span style="color:blue;"&gt;for&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt; i = &lt;span style="color:maroon;"&gt;1&lt;/span&gt;; i &amp;lt;= maxlen; ++i) {&lt;br /&gt;       &lt;span style="color:blue;"&gt;string&lt;/span&gt; s = compound.substr(cpos, i);      &lt;br /&gt;       &lt;span style="color:blue;"&gt;if&lt;/span&gt;(dict.count(s)) {&lt;br /&gt;           checkmin(res, &lt;span style="color:maroon;"&gt;1&lt;/span&gt;+solve(compound, cpos+i));&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;   &lt;span style="color:blue;"&gt;return&lt;/span&gt; memo[cpos] = res;&lt;br /&gt;}  &lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt; WordParts::partCount(&lt;span style="color:blue;"&gt;string&lt;/span&gt; original, &lt;span style="color:blue;"&gt;string&lt;/span&gt; compound) {&lt;br /&gt;   dict.clear(); &lt;span style="color:green;"&gt;// don’t forget to reset dict&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:green;"&gt;// add the whole word&lt;/span&gt;&lt;br /&gt;   dict.insert(original);&lt;br /&gt;   &lt;span style="color:green;"&gt;// add all prefix&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:blue;"&gt;for&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt; i = &lt;span style="color:maroon;"&gt;1&lt;/span&gt;; i &amp;lt;= original.length()-&lt;span style="color:maroon;"&gt;1&lt;/span&gt;; ++i)&lt;br /&gt;       dict.insert(original.substr(&lt;span style="color:maroon;"&gt;0&lt;/span&gt;,i));&lt;br /&gt;   &lt;span style="color:green;"&gt;// add all suffix&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:blue;"&gt;for&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt; i = &lt;span style="color:maroon;"&gt;1&lt;/span&gt;; i &amp;lt;= original.length()-&lt;span style="color:maroon;"&gt;1&lt;/span&gt;; ++i)&lt;br /&gt;       dict.insert(original.substr(i));&lt;br /&gt;&lt;br /&gt;   memset(memo, -&lt;span style="color:maroon;"&gt;1&lt;/span&gt;, &lt;span style="color:blue;"&gt;sizeof&lt;/span&gt;(memo));&lt;br /&gt;   &lt;span style="color:blue;"&gt;int&lt;/span&gt; res = solve(compound, &lt;span style="color:maroon;"&gt;0&lt;/span&gt;);&lt;br /&gt;   &lt;span style="color:blue;"&gt;if&lt;/span&gt;(res == INF) &lt;span style="color:blue;"&gt;return&lt;/span&gt; -&lt;span style="color:maroon;"&gt;1&lt;/span&gt;;&lt;br /&gt;   &lt;span style="color:blue;"&gt;return&lt;/span&gt; res;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-7711849327114131657?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/7711849327114131657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/7711849327114131657'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/wordparts.html' title='WordParts'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-886505155913041235</id><published>2008-09-19T08:06:00.000-07:00</published><updated>2008-09-19T08:43:27.210-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>dancing couples</title><content type='html'>topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=9902&amp;amp;rd=13507"&gt;DancingCouples&lt;/a&gt;  &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm416"&gt;editorial&lt;/a&gt;&lt;br /&gt;"Each subproblem is clearly defined by three variables: the set of unmatched boys, the set of unmatched girls, and the number of couples we need to make."&lt;br /&gt;&lt;pre&gt;d[i][j][k]  ----- the total ways to make k couples &lt;br /&gt;  |  |  |&lt;br /&gt;  |  |  i couples to make&lt;br /&gt;  |  available girl status (bitmask)&lt;br /&gt;  the i-th boy to match&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;d[i][j][k] = the ways to make k couples in which we do not use the i-th boy +&lt;br /&gt;             the ways to make k couples in which we use the i-th boy&lt;br /&gt;           = d[i-1][j][k] + sum (d[i-1][j^(1 &lt;&lt; k)][k-1])&lt;br /&gt;                         {k|A[k][j]='Y'}&lt;/pre&gt;对比上一贴：&lt;pre&gt;&lt;br /&gt;cnt [v][s] = the ways in which z6 = 0 + the ways in which z6 &gt; 0&lt;br /&gt;           = cnt[v-1][s] + cnt[v][s-v]&lt;/pre&gt;The code: &lt;pre&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; dp[&lt;span style=' color: Maroon;'&gt;12&lt;/span&gt;][&lt;span style=' color: Maroon;'&gt;1025&lt;/span&gt;][&lt;span style=' color: Maroon;'&gt;12&lt;/span&gt;];&lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; solve(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; nboy, &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; available_girl, &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; K) {&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(nboy &amp;lt; K || count_bit(available_girl) &amp;lt; K) &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(K == &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(dp[nboy][available_girl][K] &amp;gt;= &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;) &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; dp[nboy][available_girl][K];&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; res = solve(nboy-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, available_girl, K);&lt;br /&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; i = &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;; i &amp;lt; cd[&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;].size(); ++i) {&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(cd[nboy-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;][i] == &lt;span style=' color: Maroon;'&gt;'Y'&lt;/span&gt; &amp;amp;&amp;amp; available_girl &amp;amp; (&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;&amp;lt;&amp;lt;i))&lt;br /&gt;            res += solve(nboy-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, available_girl ^ (&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;&amp;lt;&amp;lt;i), K-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; dp[nboy][available_girl][K] = res;&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-886505155913041235?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/886505155913041235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/886505155913041235'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/dancing-couples.html' title='dancing couples'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-4478868233917382798</id><published>2008-09-19T04:26:00.000-07:00</published><updated>2008-09-22T18:23:48.185-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>knapsack problem</title><content type='html'>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Knapsack_problem"&gt;0/1 Knapsack Problem&lt;/a&gt;&lt;/p&gt;n items (U = {u1, u2, … , u_n} ) need to be packed in a knapsack of size C. Each item has value v_i and size s_i.We want to find a subset of U such that&lt;br&gt; &lt;p&gt;sum_ vi is maximized subject to the constraint&lt;/p&gt;sum_si &amp;lt;= C&lt;br&gt;&lt;br&gt;let V[i][j] denote the value obtained by filling a knapsack of size j with items taken from the first i items in an optimal way.&lt;br&gt; &lt;ul&gt; &lt;li&gt;V[i][j] = 0 (if i = 0 or j = 0)&lt;br&gt; &lt;li&gt;V[i][j] = V[i-1][j] ( if j &amp;lt; si )&lt;br&gt; &lt;li&gt;V[i][j] = max ( V[i-1][j], V[i-1][j-si] + vi ) ( if i &amp;gt; 0 and j &amp;gt;= si )&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;相关的dp题&lt;br&gt; &lt;ul&gt; &lt;li&gt;UVa: 10130 &lt;a href="http://acm.uva.es/p/v101/10130.html"&gt;SuperSale&lt;/a&gt;&lt;br&gt; &lt;li&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=9904&amp;amp;rd=13507"&gt;CustomDice&lt;/a&gt;  &lt;li&gt;Zoj 1149: &lt;a href="http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=149"&gt;Dividing&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;SuperSale:: 标准knapsack, 每人来一轮knapsack  &lt;div style="font-family: courier new"&gt;#include &amp;lt;iostream&amp;gt; &lt;br&gt;#include &amp;lt;vector&amp;gt; &lt;br&gt;#include &amp;lt;algorithm&amp;gt; &lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;using&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue"&gt;namespace&lt;/span&gt; std; &lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; C[&lt;span style="color: maroon"&gt;1001&lt;/span&gt;][&lt;span style="color: maroon"&gt;31&lt;/span&gt;]; &lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; Vi[&lt;span style="color: maroon"&gt;1001&lt;/span&gt;], Wi[&lt;span style="color: maroon"&gt;1001&lt;/span&gt;]; &lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; MW[&lt;span style="color: maroon"&gt;31&lt;/span&gt;]; &lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;void&lt;/span&gt; knapsack(&lt;span style="color: blue"&gt;int&lt;/span&gt; N, &lt;span style="color: blue"&gt;int&lt;/span&gt; MaxW) { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; i &amp;lt; N; ++i) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C[i][&lt;span style="color: maroon"&gt;0&lt;/span&gt;] = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; w = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; w &amp;lt;= MaxW; ++w) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C[&lt;span style="color: maroon"&gt;0&lt;/span&gt;][w] = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; i &amp;lt;= N; ++i) { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;for&lt;/span&gt;( &lt;span style="color: blue"&gt;int&lt;/span&gt; w = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; w &amp;lt;= MaxW; ++w) { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;if&lt;/span&gt;(Wi[i] &amp;gt; w) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C[i][w] = C[i-&lt;span style="color: maroon"&gt;1&lt;/span&gt;][w]; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;else&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C[i][w] = max(C[i-&lt;span style="color: maroon"&gt;1&lt;/span&gt;][w], C[i-&lt;span style="color: maroon"&gt;1&lt;/span&gt;][w-Wi[i]] + Vi[i]); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;} &lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; main() { &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;int&lt;/span&gt; T; cin &amp;gt;&amp;gt; T; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; t = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; t &amp;lt; T; ++t) { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;int&lt;/span&gt; N; cin &amp;gt;&amp;gt; N; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; i &amp;lt;= N; ++i) { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cin &amp;gt;&amp;gt; Vi[i] &amp;gt;&amp;gt; Wi[i]; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;int&lt;/span&gt; G; cin &amp;gt;&amp;gt; G; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; i &amp;lt; G; ++i) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cin &amp;gt;&amp;gt; MW[i]; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;int&lt;/span&gt; total = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;int&lt;/span&gt; maxw = *max_element(MW, MW + G); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; knapsack(N, maxw); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; i &amp;lt; G; ++i) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; total += C[N][MW[i]]; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout &amp;lt;&amp;lt; total &amp;lt;&amp;lt; endl; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: maroon"&gt;0&lt;/span&gt;; &lt;br&gt;}&lt;/div&gt;&lt;br&gt;&lt;br&gt;topcoder &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=match_editorials&amp;amp;d2=srm416"&gt;editorial&lt;/a&gt; 对第一题有很详细的讲解，中心意思是简化问题先，将原问题转化为一个更易表达和编程的形式。最后是这个形式：&lt;br&gt;&lt;pre&gt;0 ≤ z1, ..., z6&lt;br&gt;z1 + 2z2 + ... + 6z6 ≤ 6M-21 &lt;/pre&gt;&lt;br&gt;"We can now count the number of valid sequences as follows. There are two types of valid sequences: Those where z6&amp;gt;0 and those where z6=0. In the first case, we can subtract 1 from z6, and get the same problem with the right side of the inequality smaller by 6. In the second case, we get a similar problem with only 5 variables.&lt;br&gt;&lt;br&gt;This can be formulated as a recurrence relation. Let cnt[v][s] be the number of ways in which we can set variables z1 to zv so that the total (z1 + ... + vzv) does not exceed s. Then we have: cnt[v][s] = cnt[v-1][s] + cnt[v][s-v]. "&lt;br&gt;&lt;br&gt;第二个题即：&lt;br&gt;&lt;pre&gt;0≤z1≤a1,..., 0≤z6≤a6&lt;br&gt;z1 + 2z2 + ... + 6z6 = (a1 + a2 + ... + a6)/2&lt;/pre&gt;如果没有a1,...,a6的限制，跟题1几乎一样了，只要把"+"改成"||"就行了。&lt;pre&gt;cnt[v][s] = cnt[v-1][s] || cnt[v][s-v].&lt;/pre&gt;&lt;br&gt;但跟题1的一点不同是z1,...,z6有上限，所以dp过程中我们记录了zv已经用了几次。而且这题只要知道能不能"="(平分）即可，我们用0表示否，1表示可以（zv一次没用），2（zv用了一次），..., i(zv用了i-1次了）,...&lt;br&gt;&lt;pre&gt;        &lt;span style="color: blue"&gt;int&lt;/span&gt; maxsum = &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; v = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; v &amp;lt;= &lt;span style="color: maroon"&gt;6&lt;/span&gt;; ++v) {&lt;br&gt;     maxsum += v * a[v];&lt;br&gt;     &lt;span style="color: blue"&gt;if&lt;/span&gt; (maxsum &amp;gt; sum) maxsum = sum;&lt;br&gt;     cnt[v][&lt;span style="color: maroon"&gt;0&lt;/span&gt;] = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; &lt;span style="color: green"&gt;// zero can be partitioned&lt;/span&gt;&lt;br&gt;     &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; s = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; s &amp;lt;= maxsum; ++s) {&lt;br&gt;         cnt[v][s] = cnt[v-&lt;span style="color: maroon"&gt;1&lt;/span&gt;][s] &amp;gt; &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt;         &lt;span style="color: blue"&gt;if&lt;/span&gt;(cnt[v][s] == &lt;span style="color: maroon"&gt;1&lt;/span&gt;) &lt;span style="color: blue"&gt;continue&lt;/span&gt;;&lt;br&gt;         &lt;span style="color: blue"&gt;if&lt;/span&gt;(s &amp;gt;= v &amp;amp;&amp;amp; cnt[v][s-v]) {&lt;br&gt;             &lt;span style="color: blue"&gt;if&lt;/span&gt;(cnt[v][s-v] - &lt;span style="color: maroon"&gt;1&lt;/span&gt; &amp;lt; a[v]) cnt[v][s] = cnt[v][s-v]+&lt;span style="color: maroon"&gt;1&lt;/span&gt;;&lt;br&gt;         }&lt;br&gt;     }&lt;br&gt; }&lt;br&gt;&lt;/pre&gt;&lt;br&gt;下面完整的code也用了题1的技巧，用v%2省了2/3的memory,速度也由63ms降为1ms以下。因为dp每次只用上一轮的结果，e.g.,算cnt[5][s]的时候只用cnt[4][s]。&lt;pre&gt;#&lt;span style="color: blue"&gt;include&lt;/span&gt; &amp;lt;&lt;span style="color: blue"&gt;iostream&lt;/span&gt;&amp;gt;&lt;br&gt;&lt;span style="color: blue"&gt;#define&lt;/span&gt; N &lt;span style="color: maroon"&gt;20000&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; cnt[&lt;span style="color: maroon"&gt;2&lt;/span&gt;][&lt;span style="color: maroon"&gt;6&lt;/span&gt;*N/&lt;span style="color: maroon"&gt;2&lt;/span&gt;+&lt;span style="color: maroon"&gt;1&lt;/span&gt;];&lt;br&gt;&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; main() {&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; a[&lt;span style="color: maroon"&gt;7&lt;/span&gt;] = {&lt;span style="color: maroon"&gt;0&lt;/span&gt;};&lt;br&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; t = &lt;span style="color: maroon"&gt;1&lt;/span&gt;;&lt;br&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt;(scanf(&lt;span style="color: maroon"&gt;"%d %d %d %d %d %d"&lt;/span&gt;,&lt;br&gt;     &amp;amp;a[&lt;span style="color: maroon"&gt;1&lt;/span&gt;],&amp;amp;a[&lt;span style="color: maroon"&gt;2&lt;/span&gt;],&amp;amp;a[&lt;span style="color: maroon"&gt;3&lt;/span&gt;],&amp;amp;a[&lt;span style="color: maroon"&gt;4&lt;/span&gt;],&amp;amp;a[&lt;span style="color: maroon"&gt;5&lt;/span&gt;],&amp;amp;a[&lt;span style="color: maroon"&gt;6&lt;/span&gt;])!= EOF &amp;amp;&amp;amp;&lt;br&gt;     (a[&lt;span style="color: maroon"&gt;1&lt;/span&gt;] || a[&lt;span style="color: maroon"&gt;2&lt;/span&gt;] || a[&lt;span style="color: maroon"&gt;3&lt;/span&gt;] || a[&lt;span style="color: maroon"&gt;4&lt;/span&gt;] || a[&lt;span style="color: maroon"&gt;5&lt;/span&gt;] || a[&lt;span style="color: maroon"&gt;6&lt;/span&gt;])) {&lt;br&gt;&lt;br&gt; printf(&lt;span style="color: maroon"&gt;"Collection #%d:\n"&lt;/span&gt;, t++);&lt;br&gt; &lt;span style="color: blue"&gt;int&lt;/span&gt; sum = &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; i &amp;lt;= &lt;span style="color: maroon"&gt;6&lt;/span&gt;; ++i)&lt;br&gt;     sum += i * a[i];&lt;br&gt;&lt;br&gt; &lt;span style="color: green"&gt;// odd sum&lt;/span&gt;&lt;br&gt; &lt;span style="color: blue"&gt;if&lt;/span&gt;(sum &amp;amp; &lt;span style="color: maroon"&gt;1&lt;/span&gt;) {&lt;br&gt;     printf(&lt;span style="color: maroon"&gt;"Can't be divided.\n"&lt;/span&gt;);&lt;br&gt;     printf(&lt;span style="color: maroon"&gt;"\n"&lt;/span&gt;);&lt;br&gt;     &lt;span style="color: blue"&gt;continue&lt;/span&gt;;&lt;br&gt; }&lt;br&gt; sum = sum &amp;gt;&amp;gt; &lt;span style="color: maroon"&gt;1&lt;/span&gt;; &lt;span style="color: green"&gt;// divided by 2&lt;/span&gt;&lt;br&gt; memset(cnt, &lt;span style="color: maroon"&gt;0&lt;/span&gt;, &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(cnt));&lt;br&gt;&lt;br&gt; cnt[&lt;span style="color: maroon"&gt;0&lt;/span&gt;][&lt;span style="color: maroon"&gt;0&lt;/span&gt;] = &lt;span style="color: maroon"&gt;1&lt;/span&gt;;&lt;br&gt;&lt;br&gt; &lt;span style="color: blue"&gt;int&lt;/span&gt; maxsum = &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt; &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; v = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; v &amp;lt;= &lt;span style="color: maroon"&gt;6&lt;/span&gt;; ++v) {&lt;br&gt;     maxsum += v * a[v];&lt;br&gt;     &lt;span style="color: blue"&gt;if&lt;/span&gt; (maxsum &amp;gt; sum) maxsum = sum;&lt;br&gt;     cnt[&lt;span style="color: maroon"&gt;0&lt;/span&gt;][&lt;span style="color: maroon"&gt;0&lt;/span&gt;] = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; &lt;span style="color: green"&gt;// zero can be partitioned&lt;/span&gt;&lt;br&gt;     &lt;span style="color: blue"&gt;for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; s = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; s &amp;lt;= maxsum; ++s) {&lt;br&gt;         cnt[v%&lt;span style="color: maroon"&gt;2&lt;/span&gt;][s] = cnt[&lt;span style="color: maroon"&gt;1&lt;/span&gt;-v%&lt;span style="color: maroon"&gt;2&lt;/span&gt;][s] &amp;gt; &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt;         &lt;span style="color: blue"&gt;if&lt;/span&gt;(cnt[v%&lt;span style="color: maroon"&gt;2&lt;/span&gt;][s] == &lt;span style="color: maroon"&gt;1&lt;/span&gt;) &lt;span style="color: blue"&gt;continue&lt;/span&gt;;&lt;br&gt;         &lt;span style="color: blue"&gt;if&lt;/span&gt;(s &amp;gt;= v &amp;amp;&amp;amp; cnt[v%&lt;span style="color: maroon"&gt;2&lt;/span&gt;][s-v]) {&lt;br&gt;             &lt;span style="color: blue"&gt;if&lt;/span&gt;(cnt[v%&lt;span style="color: maroon"&gt;2&lt;/span&gt;][s-v] - &lt;span style="color: maroon"&gt;1&lt;/span&gt; &amp;lt; a[v]) cnt[v%&lt;span style="color: maroon"&gt;2&lt;/span&gt;][s] = cnt[v%&lt;span style="color: maroon"&gt;2&lt;/span&gt;][s-v]+&lt;span style="color: maroon"&gt;1&lt;/span&gt;;&lt;br&gt;         }&lt;br&gt;     }&lt;br&gt; }&lt;br&gt;&lt;br&gt; &lt;span style="color: blue"&gt;if&lt;/span&gt;(cnt[&lt;span style="color: maroon"&gt;0&lt;/span&gt;][sum]) printf(&lt;span style="color: maroon"&gt;"Can be divided.\n"&lt;/span&gt;);&lt;br&gt; &lt;span style="color: blue"&gt;else&lt;/span&gt; printf(&lt;span style="color: maroon"&gt;"Can't be divided.\n"&lt;/span&gt;);&lt;br&gt; printf(&lt;span style="color: maroon"&gt;"\n"&lt;/span&gt;);&lt;br&gt;}&lt;br&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: maroon"&gt;0&lt;/span&gt;;&lt;br&gt;}&lt;/pre&gt;来一个例子：&lt;br&gt;&lt;pre&gt;&lt;br&gt;-----------------------&lt;br&gt;z1  z2  z3  z4  z5  z6&lt;br&gt;-----------------------&lt;br&gt;1   1   2   1   1   1&lt;br&gt;-----------------------&lt;br&gt;&lt;br&gt;sum = 24, target = sum/2 = 12&lt;br&gt;-------------------------------------&lt;br&gt;s |[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10][11][12][13]&lt;br&gt;---------+----------------------------------------------------------&lt;br&gt;cnt[1][s]| 1   2   0&lt;br&gt;--------------------------------------------------------------------&lt;br&gt;cnt[2][s]| 1   1   2   2   0&lt;br&gt;--------------------------------------------------------------------&lt;br&gt;cnt[3][2]| 1   1   1   1   2   2   2   3   3   3   0&lt;br&gt;--------------------------------------------------------------------&lt;br&gt;cnt[4][2]| 1   1   1   1   1   1   1   1   1   1   2   2   2   0&lt;br&gt;--------------------------------------------------------------------&lt;br&gt;cnt[5][2]| ......&lt;br&gt;--------------------------------------------------------------------&lt;/pre&gt;&lt;br&gt;&lt;br&gt;又碰到一道类似的，也放在这了&lt;br&gt;topCoder: &lt;a href="http://www.topcoder.com/stat?c=problem_statement&amp;amp;pm=1919"&gt;windowWasher&lt;/a&gt;&lt;br&gt;&lt;pre&gt;0≤z1,z2,...,zn&lt;br&gt;z1 + z2 + ... + zn = width of the wall (每种worker的人数之和等于wall width)&lt;br&gt;minimize max(T1 x z1, T2 x z2, ..., Tn x Zn) (最小化总时间，大家可以并行干活)&lt;br&gt;dp recurrence:&lt;br&gt;&lt;span style="color: rgb(255,0,0)"&gt;cnt[v][s]&lt;/span&gt; =    &lt;span style="color: rgb(255,0,0)"&gt;min(cnt[v-1][s], max(cnt[v-1][s-n], T[v]*n))&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(255,0,0)"&gt;             n=1..s&lt;/span&gt;&lt;br&gt;          =    &lt;span style="color: rgb(255,0,0)"&gt;min(max(cnt[v-1][s-n], T[v]*n))&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(255,0,0)"&gt;             n=0..s&lt;/span&gt;&lt;br&gt;启用第v个worker时，两种情况：&lt;br&gt;1. 不用这个worker，只用前v-1个worker&lt;br&gt;2. 用这个worker 1次,2次, ... s次&lt;/pre&gt;只比前两题多一层循环，同样可以用% 2的方法，这里没用了。 &lt;br /&gt;&lt;div style="font-family: courier new"&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; cnt[&lt;span style="color: maroon"&gt;51&lt;/span&gt;][&lt;span style="color: maroon"&gt;1001&lt;/span&gt;];&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: courier new"&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; WindowWasher::fastest(&lt;span style="color: blue"&gt;int&lt;/span&gt; width, &lt;span style="color: blue"&gt;int&lt;/span&gt; height, vector &amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; washTimes) {&lt;br&gt;&lt;span style="color: blue"&gt;&amp;nbsp; int&lt;/span&gt; N = washTimes.size();&lt;br&gt;&amp;nbsp; vector&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; T(N+&lt;span style="color: maroon"&gt;1&lt;/span&gt;);&lt;br&gt;&lt;span style="color: blue"&gt;&amp;nbsp; for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; i = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; i &amp;lt;= N; ++i)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T[i] = height * washTimes[i-&lt;span style="color: maroon"&gt;1&lt;/span&gt;];&lt;br&gt;&amp;nbsp; memset(cnt, -&lt;span style="color: maroon"&gt;1&lt;/span&gt;, &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(cnt));&lt;br&gt;&lt;br&gt;&lt;span style="color: green"&gt;&amp;nbsp; // use only the first worker&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue"&gt;&amp;nbsp; for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; s = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; s &amp;lt;= width; ++s)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cnt[&lt;span style="color: maroon"&gt;1&lt;/span&gt;][s] = s*T[&lt;span style="color: maroon"&gt;1&lt;/span&gt;];&lt;br&gt;&lt;br&gt;&lt;span style="color: green"&gt;&amp;nbsp; // start from only one worker, add worker one by one&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue"&gt;&amp;nbsp; for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; v = &lt;span style="color: maroon"&gt;2&lt;/span&gt;; v &amp;lt;= N; ++v) {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cnt[v][&lt;span style="color: maroon"&gt;0&lt;/span&gt;] = &lt;span style="color: maroon"&gt;0&lt;/span&gt;; &lt;span style="color: green"&gt;// no work! no time needed!&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; s = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; s &amp;lt;= width; ++s) {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cnt[v][s] = cnt[v-&lt;span style="color: maroon"&gt;1&lt;/span&gt;][s]; &lt;span style="color: green"&gt;// do not use worker v, use v-1 worker only&lt;/span&gt;&lt;br&gt;&lt;span style="color: green"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // worker v works on 1,2,...,s columns&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for&lt;/span&gt;(&lt;span style="color: blue"&gt;int&lt;/span&gt; n = &lt;span style="color: maroon"&gt;1&lt;/span&gt;; n &amp;lt;= s; ++n)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; checkmin(cnt[v][s], max(cnt[v-&lt;span style="color: maroon"&gt;1&lt;/span&gt;][s-n], T[v]*n));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp; }&lt;br&gt;&lt;span style="color: blue"&gt;&amp;nbsp; return&lt;/span&gt; cnt[N][width];&lt;br&gt;}&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-4478868233917382798?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4478868233917382798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/4478868233917382798'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/dividing.html' title='knapsack problem'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-8778597967367686869</id><published>2008-09-18T14:04:00.000-07:00</published><updated>2008-10-21T12:48:42.457-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dp'/><title type='text'>Matrix Chain Multiplication</title><content type='html'>经典教科书题&lt;br /&gt;&lt;ul&gt;&lt;li&gt;zoj 1602: &lt;a href="http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=602"&gt;&lt;span class="bigProblemTitle"&gt;Multiplication Puzzle&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;UVa 442: &lt;a href="http://acm.uva.es/p/v4/442.html"&gt;Matrix Chain Multiplication&lt;/a&gt; (not really dp problem)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UVa 348: &lt;a href="http://acm.uva.es/p/v3/348.html"&gt;Optimal Array Multiplication Sequence&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;N个矩阵，N+1个维数&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Matrix:     0 ...... N-1&lt;br /&gt;-----------+---------------------------------------------------------&lt;br /&gt;Matrix dim:| (M0 x M1) x (M1 x M2) x (M2 x M3) x ... x (M_N-1 x M_N)&lt;br /&gt;-----------+---------------------------------------------------------&lt;br /&gt;Matrix  |     0           1           2                   N-1 &lt;br /&gt;---------------------------------------------------------------------&lt;/pre&gt;&lt;br /&gt;The i-th matrix's dimension: M_(i-1) x M_i&lt;br /&gt;第i到j个矩阵相乘的代价&lt;pre&gt;&lt;br /&gt;d[i][i] = 0&lt;br /&gt;d[i][j] = min(d[i][j], d[i][k]+d[k+1][j]+ M_(i-1)*M_(k)*M_(j))&lt;/pre&gt;&lt;pre&gt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt; C[N+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;][N+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;];&lt;br /&gt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt; K[N+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;][N+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;];&lt;br /&gt;&lt;span style="color:Blue;"&gt;void&lt;/span&gt; mcm(vector&amp;lt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&amp;gt; &amp;amp;M, &lt;span style="color:Blue;"&gt;int&lt;/span&gt; n) {&lt;br /&gt; &lt;span style="color:Blue;"&gt;for&lt;/span&gt;(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = &lt;span style="color:Maroon;"&gt;1&lt;/span&gt;; i &amp;lt;= n; ++i)&lt;br /&gt;     C[i][i] = &lt;span style="color:Maroon;"&gt;0&lt;/span&gt;;&lt;br /&gt; &lt;span style="color:Blue;"&gt;for&lt;/span&gt;(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; d = &lt;span style="color:Maroon;"&gt;2&lt;/span&gt;; d &amp;lt;= n; ++d) {&lt;br /&gt;     &lt;span style="color:Blue;"&gt;for&lt;/span&gt;(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = &lt;span style="color:Maroon;"&gt;1&lt;/span&gt;; i &amp;lt;= n-d+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;; ++i) {&lt;br /&gt;         &lt;span style="color:Blue;"&gt;int&lt;/span&gt; j = i + d - &lt;span style="color:Maroon;"&gt;1&lt;/span&gt;;&lt;br /&gt;         C[i][j] = INF;&lt;br /&gt;         &lt;span style="color:Blue;"&gt;for&lt;/span&gt;(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; k = i; k &amp;lt;= j-&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;; ++k) {&lt;br /&gt;             &lt;span style="color:Blue;"&gt;int&lt;/span&gt; tmp = C[i][k] + C[k+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;][j] + M[i-&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;] * M[k] * M[j];&lt;br /&gt;             &lt;span style="color:Blue;"&gt;if&lt;/span&gt;( tmp &amp;lt; C[i][j]) {&lt;br /&gt;                 K[i][j] = k;&lt;br /&gt;                 C[i][j] = tmp;&lt;br /&gt;             }&lt;br /&gt;         }&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt; C[1][N]中存着从1到N连乘最小的代价，从K[][]可以得到路径。&lt;pre&gt;&lt;span style="color:Blue;"&gt;void&lt;/span&gt; print_opt(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i, &lt;span style="color:Blue;"&gt;int&lt;/span&gt; j) {&lt;br /&gt; &lt;span style="color:Blue;"&gt;if&lt;/span&gt;(i == j)&lt;br /&gt;     &lt;span style="color:Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span style="color:Maroon;"&gt;"A"&lt;/span&gt; &amp;lt;&amp;lt; i;&lt;br /&gt; &lt;span style="color:Blue;"&gt;else&lt;/span&gt; {&lt;br /&gt;     &lt;span style="color:Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span style="color:Maroon;"&gt;"("&lt;/span&gt;;&lt;br /&gt;     print_opt(i, K[i][j]);&lt;br /&gt;     &lt;span style="color:Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span style="color:Maroon;"&gt;" x "&lt;/span&gt;;&lt;br /&gt;     print_opt(K[i][j]+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;, j);&lt;br /&gt;     &lt;span style="color:Blue;"&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span style="color:Maroon;"&gt;")"&lt;/span&gt;;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;调用时传入mcm()一个长度为N+1的数组，和N(不是N+1!）&lt;pre&gt;vector&amp;lt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&amp;gt; M(n+&lt;span style="color:Maroon;"&gt;1&lt;/span&gt;);&lt;br /&gt;mcm(M, n);&lt;br /&gt;&lt;/pre&gt;下面是memoization的版本，编程简单&lt;br /&gt;&lt;pre&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; lookupMcm(vector&amp;lt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt;&amp;gt; &amp;amp;M, &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; i, &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; j) {&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(C[i][j] != INF) &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; C[i][j];&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(i == j)&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; C[i][j] = &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; k = i; k &amp;lt; j; ++k) {&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; q = lookupMcm(M, i, k) + lookupMcm(M, k+&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, j) + M[i-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;] * M[k] * M[j];&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;( C[i][j] &amp;gt; q)&lt;br /&gt;            C[i][j] = q;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;return&lt;/span&gt; C[i][j];&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;调用前将C[][]初始化为INF&lt;br /&gt;&lt;pre&gt;&lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; i = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; i &amp;lt;= n; ++i)&lt;br /&gt;            &lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; j = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; j &amp;lt;= n; ++j)&lt;br /&gt;                C[i][j] = INF;&lt;br /&gt;&lt;br /&gt;printf(&lt;span style=' color: Maroon;'&gt;"%d\n"&lt;/span&gt;,  lookupMcm(M, &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;, n));&lt;/pre&gt;&lt;pre&gt;Similarly, this technique can be used to solove the following problem: (in today's interview (oct 21) )&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;find the length of the longest regular brackets sequence that is a subsequence of s&lt;br /&gt;&lt;p&gt;主要思想就是从中间出发，往两边发展，&lt;br /&gt;&lt;p&gt;如果已和dp[i][j]则考虑 dp[i-1][j+1]&lt;br /&gt;&lt;p&gt;if&amp;nbsp; s[i-1] match s[j+1], then dp[i-1][j+1] = dp[i][j]&lt;br /&gt;&lt;p&gt;else&amp;nbsp; dp[i-1][j+1] = max (dp[i-1][k] + dp[k+1][j+1]) &lt;pre&gt;#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;#include &amp;lt;cstring&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; MAX = 101;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// dynamic programming 2d array&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; dp[MAX][MAX];&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// return true if find matching brackets&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;inline&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; match(&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; a, &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; b) {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(a == '(' &amp;amp;&amp;amp; b == ')') &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(a == '[' &amp;amp;&amp;amp; b == ']') &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main() {&lt;/pre&gt;&lt;pre&gt;  &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; buff[MAX];&lt;br /&gt;   &lt;br /&gt;  &lt;span style="color: #008000"&gt;// terminate until "end"&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; (gets(buff) &amp;amp;&amp;amp; buff[0] != 'e') {&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; n = strlen(buff);&lt;br /&gt;    memset(dp, 0, &lt;span style="color: #0000ff"&gt;sizeof&lt;/span&gt;(dp));&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++ i)&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (match(buff[i],buff[i+1]))&lt;br /&gt;      dp[i][i+1] = 2;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; k = 2; k &amp;lt; n; ++ k) {&lt;br /&gt;       &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; ++ i) {&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (k + i &amp;lt; n) {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (match(buff[i], buff[i+k]))&lt;br /&gt;                dp[i][i+k] = dp[i+1][i+k-1] + 2;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = i; j &amp;lt; i + k; ++ j) {&lt;br /&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (dp[i][j] + dp[j+1][i+k] &amp;gt; dp[i][i+k])&lt;br /&gt;             dp[i][i+k] = dp[j+1][i+k] + dp[i][j];&lt;br /&gt;            }&lt;br /&gt;          }&lt;br /&gt;       }     &lt;br /&gt;    }&lt;br /&gt;    printf("&lt;span style="color: #8b0000"&gt;%d\n&lt;/span&gt;", dp[0][n-1]);&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10239043-8778597967367686869?l=greeness2008.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8778597967367686869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10239043/posts/default/8778597967367686869'/><link rel='alternate' type='text/html' href='http://greeness2008.blogspot.com/2008/09/matrix-chain-multiplication.html' title='Matrix Chain Multiplication'/><author><name>greeness</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-10239043.post-3361219892247954351</id><published>2008-09-17T12:17:00.001-07:00</published><updated>2008-09-18T07:56:29.415-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='graph'/><category scheme='http://www.blogger.com/atom/ns#' term='bit operation'/><title type='text'>Triangle War II (ZJU Sep 2008 contest)</title><content type='html'>&lt;a href="http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=2036"&gt;ZOJ Problem Set - 3038&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;一开始以为是lights out这种puzzle,仔细看发现只能按unpushed button, 这是与lights out 类问题严重的不同，不是finite field。只好上brute force, 最多状态，2^21还是可行的，先试了DFS,发现stack overflow, 然后用BFS搞定，发生了一点小问题，visited忘了reset...&lt;br /&gt;&lt;br /&gt;这道题里用bit operation很方便的。&lt;br /&gt;&lt;ul&gt;&lt;li&gt;首先把adj matrix表示成N个bit vector,每个bit vector是从一个结点出发的所有边。&lt;/li&gt;&lt;li&gt;同样将当前图的状态也表示成一个N位的bit vector (status, 1 表示unpushed, 0表示pushed)。&lt;br /&gt;&lt;/li&gt;&lt;li&gt;用bit vector i 同当前graph结点的状态 status 异或就直接得到push button i后的结点状态。&lt;/li&gt;&lt;/ul&gt;下面的code是查看当前graph结点i 是否是unpushed， 如果是则按下它得到之后的状态。&lt;br /&gt;&lt;pre class="code"&gt;if(status &amp;amp;(1 &lt;&lt; i))       &lt;br /&gt; status = status ^ adj[i];&lt;/pre&gt;&lt;pre&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;queue&amp;gt;&lt;br /&gt;#&lt;span style=' color: Blue;'&gt;include&lt;/span&gt; &amp;lt;ctime&amp;gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;using&lt;/span&gt; &lt;span style=' color: Blue;'&gt;namespace&lt;/span&gt; &lt;span style=' color: Blue;'&gt;std&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Green;'&gt;// triangle size &lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;const&lt;/span&gt; &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; MAX_LEVEL = &lt;span style=' color: Maroon;'&gt;6&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Green;'&gt;// node # in the triangle&lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;const&lt;/span&gt; &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; MAX_N = (MAX_LEVEL+&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;)*(MAX_LEVEL)/&lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;short visited[(&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;&amp;lt;&amp;lt;MAX_N)+&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;];&lt;br /&gt;&lt;span style=' color: Green;'&gt;// adjancency matrix&lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; adj[MAX_N]; &lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; n; &lt;span style=' color: Green;'&gt;// # of levels&lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; maxon; &lt;span style=' color: Green;'&gt;// max # of unpushed node&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=' color: Blue;'&gt;void&lt;/span&gt; construct_adj(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; N) {&lt;br /&gt;    memset(adj, &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;, &lt;span style=' color: Blue;'&gt;sizeof&lt;/span&gt;(adj));&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; level = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; level &amp;lt;= n; ++level) {&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; i = level*(level-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;)/&lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;; &lt;span style=' color: Green;'&gt;// start point of this level&lt;/span&gt;&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; j = &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;; j &amp;lt; level; ++j) {&lt;br /&gt;            &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; a = i+j;&lt;br /&gt;            adj[a] |= (&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;&amp;lt;&amp;lt;a); &lt;span style=' color: Green;'&gt;// self connected&lt;/span&gt;&lt;br /&gt;            &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(level &amp;lt; n) {&lt;br /&gt;                adj[a] |= &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;&amp;lt;&amp;lt;(a+level);   &lt;span style=' color: Green;'&gt;// connect with left child&lt;/span&gt;&lt;br /&gt;                adj[a] |= &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;&amp;lt;&amp;lt;(a+level+&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;); &lt;span style=' color: Green;'&gt;// connect with right child&lt;/span&gt;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(j &amp;lt; level-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;) adj[a] |= &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;&amp;lt;&amp;lt;(a+&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;); &lt;span style=' color: Green;'&gt;// connect with right sibling&lt;/span&gt;&lt;br /&gt;            &lt;span style=' color: Blue;'&gt;if&lt;/span&gt;(j &amp;gt; &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;)       adj[a] |= &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;&amp;lt;&amp;lt;(a-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;); &lt;span style=' color: Green;'&gt;// connect with left sibling&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style=' color: Green;'&gt;// sysmetric filling&lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; i = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; i &amp;lt; N; ++i)&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; j = &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;; j &amp;lt; i; ++j) {&lt;br /&gt;             &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; t = adj[j] &amp;amp; (&lt;span styl
