【动态规划中级】AvoidRoads
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
收获: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
=1x4 + 4x3y + 6x2y2 + 4xy3 + 1y4

可以看出系数就是紫色的对应的部分。拆开相乘就知道譬如x2y2是由6种途径得到的,和图中所展示的一样,到达x2y2有六种途径。
很奇妙!
三维见视频。
总结:

--------------------------------------------------------------------------------------------------------------
浙公网安备 33010602011771号