zoukankan      html  css  js  c++  java
  • [BZOJ] 1616: [Usaco2008 Mar]Cow Travelling游荡的奶牛

    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)
    转载请注明出处 -- 如有意见欢迎评论
  • 相关阅读:
    使用unlist将日期型数据的列表转换为向量时,出现的异常
    => in Scala
    Scala Beginner
    .net Core 调用微信Jsapi接口,H5解析二维码
    TextBoxFor控件的扩展---Bootstrap在mvc上的应用
    Dapper Vs Dbentry
    外地手机号码,请在号码前加拨0
    Sql 2012 远程数据库连接
    DbEntry在Vs2012里的配置
    拓展:正则表达式-常用函数
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7466274.html
Copyright © 2011-2022 走看看