【动态规划中级】AvoidRoads

Problem Statement for AvoidRoads

Problem Statement

    Problem contains images. Plugin users can view them in the applet.

In the city, roads are arranged in a grid pattern. Each point on the grid represents a corner where two blocks meet. The points are connected by line segments which represent the various street blocks. Using the cartesian coordinate system, we can assign a pair of integers to each corner as shown below. 



 

You are standing at the corner with coordinates 0,0. Your destination is at corner width,height. You will return the number of distinct paths that lead to your destination. Each path must use exactly width+heightblocks. In addition, the city has declared certain street blocks untraversable. These blocks may not be a part of any path. You will be given a String[] bad describing which blocks are bad. If (quotes for clarity) "a b c d" is an element of bad, it means the block from corner a,b to corner c,d is untraversable. For example, let's say
width  = 6length = 6bad = {"0 0 0 1","6 6 5 6"}
The picture below shows the grid, with untraversable blocks darkened in black. A sample path has been highlighted in red.



 

 

Definition

    
Class:AvoidRoads
Method:numWays
Parameters:int, int, String[]
Returns:long
Method signature:long numWays(int width, int height, String[] bad)
(be sure your method is public)
    
 

Constraints

-width will be between 1 and 100 inclusive.
-height will be between 1 and 100 inclusive.
-bad will contain between 0 and 50 elements inclusive.
-Each element of bad will contain between 7 and 14 characters inclusive.
-Each element of the bad will be in the format "a b c d" where,
  • a,b,c,d are integers with no extra leading zeros,
  • a and c are between 0 and width inclusive,
  • b and d are between 0 and height inclusive,
  • and a,b is one block away from c,d.
-The return value will be between 0 and 2^63-1 inclusive.
 

Examples

0)
    
6
6
{"0 0 0 1","6 6 5 6"}
Returns: 252
Example from above.
1)
    
1
1
{}
Returns: 2
Four blocks aranged in a square. Only 2 paths allowed.
2)
    
35
31
{}
Returns: 6406484391866534976
Big number.
3)
    
2
2
{"0 0 1 0", "1 2 2 2", "1 1 2 1"}
Returns: 0

 


收获:1.阻碍是双向的。
2.和那个脑筋急转弯的思路一样,路径累加。脑筋急转弯链接见下面附。

从图中可以看出,如果边可达,那么到达roadnum[0][i]=1;
                                    roadnum[i][0]=1;
到达黄点的路径条数,roadnum[1][1]=roadnum[0][1]+roadnum[1][0]

依次类推,roadnum[i][j]=到达roadnum[i-1][j]和到达road[i][j-1]的路径之和。


#include<stdio.h>
#include<iostream>
using namespace std;
#define LEN 100
int bad[LEN][4];
int badn;
long long roadnum[LEN][LEN];
int reachable(int x1,int y1,int x2,int y2){
    for(int i=0;i<badn;i++){
        if( (x1==bad[i][0]&& y1==bad[i][1]&& x2==bad[i][2] && y2== bad[i][3]) ||
           (x1==bad[i][2]&& y1==bad[i][3]&& x2==bad[i][0]&& y2==bad[i][1]) )
            return 0;
    }
    return 1;
}

long long dp(int m,int n){
    for(int i=0;i<=m;i++){
        roadnum[i][0]=0;
        if(reachable(i,0,i-1,0)&& (i>1&&roadnum[i-1][0]>0 || i==1) )roadnum[i][0]=1;
    }
    for(int i=0;i<=n;i++){
        roadnum[0][i]=0;
        if(reachable(0,i,0,i-1)&& (i>1&&roadnum[0][i-1]>0 || i==1) )roadnum[0][i]=1;
    }

    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            roadnum[i][j]=0;
            if(reachable(i,j,i-1,j))
                roadnum[i][j]+=roadnum[i-1][j];
            if(reachable(i,j,i,j-1))
                roadnum[i][j]+=roadnum[i][j-1];
        }
    }
    return roadnum[m][n];
}
int main(){
    freopen("in.txt","r",stdin);
    int m,n;
    while(cin>>m>>n){
        cin>>badn;
        for(int i=0;i<badn;i++){
            for(int j=0;j<4;j++){
                cin>>bad[i][j];
            }
        }
        cout<<dp(m,n)<<endl;
    }
}

测试用例:
6 6
2
0 0 0 1
6 6 5 6
1 1
0
35 31
0
2 2
3
0 0 1 0
1 2 2 2
1 1 2 1

结果:
252
2
6406484391866534976
0

------------------------------------------------------------------------------------------------------------
网易公开课脑筋急转弯

这类矩阵的问题要想着先处理边。正如视频中所讲的那样
      →    

                         ↓

拓展
多项式
求(x+y)n=?
如(x+y)4
=1x+ 4x3y + 6x2y+ 4xy+ 1y4
可以看出系数就是紫色的对应的部分。拆开相乘就知道譬如x2y2是由6种途径得到的,和图中所展示的一样,到达x2y2有六种途径。
很奇妙!

三维见视频。
总结:


--------------------------------------------------------------------------------------------------------------





posted @ 2014-05-21 16:12  空暖  阅读(656)  评论(0)    收藏  举报