/*---------------------------------------------------------------------------
File name: C76-24.cpp
Author: HJin
Created on: 6/18/2007 22:53:55
C76-24.cpp --- the cpp source file for solving the 24th of the 76
classical C/C++ problems.
经典 76 道编程题 之 24:
24. 某地街道把城市分割成矩形方格,每一方格叫作块,某人从家中出发上班,
向东要走M块,向北要走N块,(见图)。请设计一个程序,由计算机寻找并
打印出所有的上班的路径。
单位
┬ ┌─┬─┬─┬─┬─┬─┬─┐
│ │ │ │ │ │ │ │ │
│ ├─┼─┼─┼─┼─┼─┼─┤
↓ │ │ │ │ │ │ │ │
N ├─┼─┼─┼─┼─┼─┼─┤
↑ │ │ │ │ │ │ │ │
│ ├─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
┴ └─┴─┴─┴─┴─┴─┴─┘
家 ├─────→M←─────┤
Analysis:
Let us
E --- the person move 1km to the east;
N --- to stand for the person move 1km to the east;
If M= 7, N =4 (as in the figure), then
E E E E E E E N N N N
means that the person travels east 7km first, then he/she travels
north 4km.
A little bit math shows that we have
binomial(M+N, M)
different ways to travel from home to work, since we have to travel
M kms to the east. A way is a choice that how we put the M E's into
M+N slots.
Sample output (for M=5, N=2):
1 EEEEENN
2 EEEENEN
3 EEEENNE
4 EEENEEN
5 EEENENE
6 EEENNEE
7 EENEEEN
8 EENEENE
9 EENENEE
10 EENNEEE
11 ENEEEEN
12 ENEEENE
13 ENEENEE
14 ENENEEE
15 ENNEEEE
16 NEEEEEN
17 NEEEENE
18 NEEENEE
19 NEENEEE
20 NENEEEE
21 NNEEEEE
correct.
Press any key to continue . . .
Reference:
1. 野比, 相当经典的76道编程自虐题分享.无答案 at
http://bbs.bc-cn.net/viewthread.php?tid=147853
*/
#include <iostream>
#include <string>
#include <set>
using namespace std;
/**
serious improvment needed: this recursive version is very inefficient.
For M=7, N=4, it takes 3 mintues to compute.
The classical algorithm to permute a string. We use a set to keep
different strings --- some permutations may repeat.
*/
void way_recursive(string& in, string& out, set<string>& ss);
/**
a wrapper of way_recursive.
*/
int way(int M, int N, bool print=true);
/** compute binomial(n, k).
* n >=k
*
*
*/
int binomial(int n, int k); // n choose k
int main(int argc, char** argv)
{
// test #1: --- the recursive way takes long time (3 mintues)
//int M=7;
//int N=4;
// test #2:
int M=5;
int N=2;
int num;
num = way(M, N);
/**
A little bit math shows that the number is binomial(M+N, M).
This is just a check to give you more confidence.
*/
if(num != binomial(M+N, M))
cout<<"wrong number.\n";
else
cout<<"correct.\n";
return 0;
}
void way_recursive(string& in, string& out, set<string>& ss)
{
// in is empty so that all chars are transferred to out buffer
// and out is a permutation of in
if( in.empty() )
{
ss.insert(out); // insert only one copy --- no duplicates
return;
}
// the way to permute a string in one statement
for(size_t i=0; i<in.size(); ++i)
way_recursive(in.substr(0, i) + in.substr(i+1), out+in[i], ss);
}
int way(int M, int N, bool print)
{
set<string> ss;
string in;
string out;
int i;
int counter = 0;
in.resize(M+N);
// the very first way
for(i=0; i<M; ++i)
in[i] = 'E';
for(i=M; i<M+N; ++i)
in[i] = 'N';
// build the set
way_recursive(in, out, ss);
if(print)
{
for(set<string>::const_iterator iter = ss.begin(); iter != ss.end(); ++iter)
{
++counter;
cout<<counter<<"\t"<<*iter<<endl;
}
}
return counter;
}
int binomial(int n, int k)
{
int res = 1;
int i;
if(k>n/2)
k = n-k;
++n;
for(i=1; i<=k; ++i)
{
res *= (n-i);
res /= i;
}
return res;
}
I am working on a system which has no Chinese input. Please don\'t blame me for typing English.