1. 程式人生 > >[BZOJ] 1616: [Usaco2008 Mar]Cow Travelling遊蕩的奶牛

[BZOJ] 1616: [Usaco2008 Mar]Cow Travelling遊蕩的奶牛

stat aps book 防止 pty open 情況 其他 在那

1616: [Usaco2008 Mar]Cow Travelling遊蕩的奶牛

Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 1312 Solved: 736
[Submit][Status][Discuss]

Description

奶牛們在被劃分成N行M列(2 <= N <= 100; 2 <= M <= 100)的草地上遊走,試圖找到整塊草地中最美味的牧草。Farmer John在某個時刻看見貝茜在位置 (R1, C1),恰好T (0 < T <= 15)秒後,FJ又在位置(R2, C2)與貝茜撞了正著。 FJ並不知道在這T秒內貝茜是否曾經到過(R2, C2),他能確定的只是,現在貝茜在那裏。 設S為奶牛在T秒內從(R1, C1)走到(R2, C2)所能選擇的路徑總數,FJ希望有一個程序來幫他計算這個值。每一秒內,奶牛會水平或垂直地移動1單位距離(奶牛總是在移動,不會在某秒內停在它上一秒所在的點)。草地上的某些地方有樹,自然,奶牛不能走到樹所在的位置,也不會走出草地。 現在你拿到了一張整塊草地的地形圖,其中‘.‘表示平坦的草地,‘*‘表示擋路的樹。你的任務是計算出,一頭在T秒內從(R1, C1)移動到(R2, C2)的奶牛可能經過的路徑有哪些。

Input

* 第1行: 3個用空格隔開的整數:N,M,T

* 第2..N+1行: 第i+1行為M個連續的字符,描述了草地第i行各點的情況,保證 字符是‘.‘和‘*‘中的一個 * 第N+2行: 4個用空格隔開的整數:R1,C1,R2,以及C2

Output

* 第1行: 輸出S,含義如題中所述

Sample Input

4 5 6
...*.
...*.
.....
.....
1 3 1 5

輸入說明:

草地被劃分成4行5列,奶牛在6秒內從第1行第3列走到了第1行第5列。

Sample Output

1

奶牛在6秒內從(1,3)走到(1,5)的方法只有一種(繞過她面前的樹)。

HINT

Source

Silver

Analysis

蒟蒻只看出這是暴搜 qwq

首先一個限定 T 步的DFS(這樣可以防止路徑重復)

證明:顯然(不會證啊qwq)

定義計數圖 cnt [ x ] [ y ] ,保存可到達點 ( x , y ) 的路徑總數

然後某一次路徑搜索在哪裏終結,就在對應點的計數圖上 +1

好的,6000+ms 為某位大佬的權限號貢獻一個TLE

考慮剪枝

如果一條路徑無法到達目的地,那麽這條路徑顯然是可以剪枝剪掉的

定義最短距離圖 Tracing [ x ] [ y ] ,保存目的地到點 ( x , y ) 的最短距離

如果在DFS的某個狀態中,剩余的步數已經不夠到達了,敢敢剪掉

上述算法用時 3288ms


然後我研究了一下其他人的版本

發現是一個什麽都不是的DP

QwQ

定義 DP [ t ] [ x ] [ y ] 為第 t 秒可以到達點 ( x , y ) 的總路徑數

那麽我們可以暴力了

代碼已Po

其實早先也有想到類似解法,但是如何防止新求出來的答案互相覆蓋呢?(天真的我一直局限於用一張地圖= =)

根據時間區別,不停繪制新地圖,就類似上述的DP狀態定義

還是太年輕啊,唉

DP用時:44ms

Code

技術分享
 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 
 5 const int dir[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
 6 
 7 int r,c,t,sx,sy,tx,ty;
 8 int map[1000][1000];
 9 int DP[20][1000][1000];
10 char str[1000];
11 
12 int main(){
13     scanf("%d%d%d",&r,&c,&t);
14     for(int i = 1;i <= r;i++){
15         scanf("%s",str);
16         for(int j = 1;j <= c;j++){
17             if(str[j-1] == .) map[i][j] = 1;
18         }
19     }scanf("%d%d%d%d",&sx,&sy,&tx,&ty);
20     
21     DP[0][sx][sy] = 1;
22     
23     for(int T = 1;T <= t;T++){
24         for(int i = 1;i <= r;i++){
25             for(int j = 1;j <= c;j++){
26                 for(int k = 0;k < 4;k++){
27                     int nowx = i+dir[k][0];
28                     int nowy = j+dir[k][1];
29                     if(!map[nowx][nowy]) continue;
30                     DP[T][i][j] += DP[T-1][nowx][nowy];
31                 }
32             }
33         }
34     }
35     
36     printf("%d",DP[t][tx][ty]);
37     
38     return 0;
39 }
我試圖在下面重新插一行,但是失敗了,這樣不符合行文順序qwq(DP) 技術分享
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<queue>
 4 using namespace std;
 5 
 6 struct node{
 7     int x,y,step;
 8 };
 9 
10 const int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
11 int r,c,t,sx,sy,tx,ty;
12 int map[1000][1000];
13 int tracing[1000][1000];
14 int cnt[1000][1000];
15 bool book[1000][1000];
16 char ctr;
17 
18 void bfs(){
19     queue<node> Q;
20     Q.push((node){tx,ty,0});
21     tracing[tx][ty] = -1;
22     
23     while(!Q.empty()){
24         node now = Q.front();
25         Q.pop();
26         
27         for(int i = 0;i < 4;i++){
28             int nowx = now.x+dir[i][0];
29             int nowy = now.y+dir[i][1];
30             if((!tracing[nowx][nowy] || tracing[nowx][nowy] >= now.step+1) && map[nowx][nowy]){
31                 tracing[nowx][nowy] = now.step+1;
32                 if(!book[nowx][nowy]){
33                     Q.push((node){nowx,nowy,now.step+1});
34                     book[nowx][nowy] = true;
35                 }
36             }
37         }
38         book[now.x][now.y] = false;
39     }
40 }
41 
42 void dfs(int nowx,int nowy,int step){
43     if(step == t) cnt[nowx][nowy]++;
44     else{
45         for(int i = 0;i < 4;i++){
46             int x = nowx+dir[i][0];
47             int y = nowy+dir[i][1];
48             
49             if(map[x][y] && step+tracing[x][y] <= t) dfs(x,y,step+1);
50         }
51     }
52 }
53 
54 int main(){
55     scanf("%d%d%d",&r,&c,&t);
56     for(int i = 1;i <= r;i++){
57         for(int j = 1;j <= c;j++){
58             cin >> ctr;
59             if(ctr == .) map[i][j] = 1;
60         }
61     }
62     
63     scanf("%d%d%d%d",&sx,&sy,&tx,&ty);
64     
65     bfs();
66     
67     dfs(sx,sy,0);
68     
69     printf("%d",cnt[tx][ty]);
70     
71 //    for(int i = 1;i <= r;i++){
72 //    /cout << endl;
73 //        for(int j = 1;j <= c;j++){
74 //            printf("%d ",tracing[i][j]);
75 //        }
76 //    }
77     
78     return 0;
79 }
不得不說雖然BZOJ用戶體驗奇差無比,但是這樣的排版可以直接搞到cnblogs上超爽的(BFS+DFS)

[BZOJ] 1616: [Usaco2008 Mar]Cow Travelling遊蕩的奶牛