题目连接:https://community.topcoder.com/stat?c=problem_statement&pm=1889&rd=4709
题意:给一张n*m的地图,上面有些路不能走,每次只能向左走或者向下走。问从(0,0)走到(n,m)一共有多少种走法。
动态规划,先哈希标记出所有无法走的道路,然后做DP。
转移方程:
如果(i-1,j)可以走到(i,j):dp(i,j)+=dp(i-1,j)
如果(i,j-1)可以走到(i,j):dp(i,j)+=dp(i,j-1)
1 // BEGIN CUT HERE 2 3 // END CUT HERE 4 #line 5 "AvoidRoads.cpp" 5 #include <cstdlib> 6 #include <cctype> 7 #include <cstring> 8 #include <cstdio> 9 #include <cmath> 10 #include <algorithm> 11 #include <vector> 12 #include <string> 13 #include <iostream> 14 #include <sstream> 15 #include <map> 16 #include <set> 17 #include <queue> 18 #include <stack> 19 #include <fstream> 20 #include <numeric> 21 #include <iomanip> 22 #include <bitset> 23 #include <list> 24 #include <stdexcept> 25 #include <functional> 26 #include <utility> 27 #include <ctime> 28 using namespace std; 29 30 typedef long long ll; 31 const int mod = 1000007; 32 bool cut[mod]; 33 unsigned long long dp[130][130]; 34 35 int cv(int x1, int y1, int x2, int y2) { 36 return ((((x1 * 1007 % mod) + y1 * 737 % mod) + x2 * 103) % mod + y2 * 71) % mod; 37 } 38 39 class AvoidRoads 40 { 41 public: 42 long long numWays(int width, int height, vector<string> bad) { 43 int x1,y1,x2,y2; 44 int& n = width; 45 int& m = height; 46 memset(cut, 0, sizeof(cut)); 47 memset(dp, 0, sizeof(dp)); 48 for(int i = 0; i < bad.size(); i++) { 49 stringstream ss; 50 ss << bad[i]; 51 ss >> x1 >> y1 >> x2 >> y2; 52 cut[cv(x1,y1,x2,y2)] = 1; 53 cut[cv(x2,y2,x1,y1)] = 1; 54 55 } 56 dp[0][0] = 1; 57 for(int i = 0; i < n; i++) { 58 if(!cut[cv(i,0,i+1,0)]) dp[i+1][0] = dp[i][0]; 59 else break; 60 } 61 for(int i = 0; i < m; i++) { 62 if(!cut[cv(0,i,0,i+1)]) dp[0][i+1] = dp[0][i]; 63 else break; 64 } 65 for(int i = 1; i <= n; i++) { 66 for(int j = 1; j <= m; j++) { 67 if(!cut[cv(i-1,j,i,j)]) dp[i][j] += dp[i-1][j]; 68 if(!cut[cv(i,j-1,i,j)]) dp[i][j] += dp[i][j-1]; 69 } 70 } 71 return dp[n][m]; 72 } 73 74 // BEGIN CUT HERE 75 public: 76 void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); } 77 private: 78 template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '"' << *iter << "","; os << " }"; return os.str(); } 79 void verify_case(int Case, const long long &Expected, const long long &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << " Expected: "" << Expected << '"' << endl; cerr << " Received: "" << Received << '"' << endl; } } 80 void test_case_0() { int Arg0 = 6; int Arg1 = 6; string Arr2[] = {"0 0 0 1","6 6 5 6"}; vector <string> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); long long Arg3 = 252LL; verify_case(0, Arg3, numWays(Arg0, Arg1, Arg2)); } 81 void test_case_1() { int Arg0 = 1; int Arg1 = 1; string Arr2[] = {}; vector <string> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); long long Arg3 = 2LL; verify_case(1, Arg3, numWays(Arg0, Arg1, Arg2)); } 82 void test_case_2() { int Arg0 = 35; int Arg1 = 31; string Arr2[] = {}; vector <string> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); long long Arg3 = 6406484391866534976LL; verify_case(2, Arg3, numWays(Arg0, Arg1, Arg2)); } 83 void test_case_3() { int Arg0 = 2; int Arg1 = 2; string Arr2[] = {"0 0 1 0", "1 2 2 2", "1 1 2 1"}; vector <string> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); long long Arg3 = 0LL; verify_case(3, Arg3, numWays(Arg0, Arg1, Arg2)); } 84 85 // END CUT HERE 86 87 }; 88 89 // BEGIN CUT HERE 90 int main() 91 { 92 AvoidRoads ___test; 93 ___test.run_test(-1); 94 return 0; 95 } 96 // END CUT HERE