zoukankan      html  css  js  c++  java
  • UVa 11694

    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2741

    题意:

    在一个 n*n(n≤7)网格中,有些交叉点上有数字。你的任务是给每个格子画一条斜线(一共只有“”和“/”两种),
    使得每个交叉点的数字等于和它相连的斜线条数,且这些斜线不会构成环。

    分析:

    深搜 + 剪枝,枚举当前位置的两种摆法,
    当当前位置是最后一个能更新某个数值的位置时,判断该数值是否为0,
    若不是,则递归返回。这样有四种情况可以剪枝。
    具体实现见代码。

    代码:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cctype>
      4 
      5 const int UP = 7 + 5;
      6 const int dr[4] = {-1, 1, -1, 1}; //左上,右下,右上,左下
      7 const int dc[4] = {-1, 1, 1, -1};
      8 const int udr[2] = {0, 0}; //反斜杠和斜杠的上方坐标
      9 const int udc[2] = {0, 1};
     10 const int ddr[2] = {1, 1}; //反斜杠和斜杠的下方坐标
     11 const int ddc[2] = {1, 0};
     12 
     13 int n, N, finish, mark, vis[UP][UP];
     14 char grid[UP][UP], ans[UP][UP], edge[UP][UP][UP][UP];
     15 //ans[r][c] 与 grid[r][c], grid[r][c+1], grid[r+1][c], grid[r+1][c+1] 相关联
     16 //r与c的下标从1开始
     17 
     18 void renew(int r1, int c1, int r2, int c2){ //恢复状态
     19     if(isdigit(grid[r1][c1])) grid[r1][c1]++;
     20     if(isdigit(grid[r2][c2])) grid[r2][c2]++;
     21 }
     22 
     23 bool loop(int r, int c, int f){ //判断是否有环
     24     if(vis[r][c] == mark) return true;
     25     vis[r][c] = mark;
     26     for(int i = 0; i < 4; i++){
     27         if((i ^ 1) == f) continue; //i的相反方向是否等于f
     28         int fr = r + dr[i], fc = c + dc[i];
     29         if(edge[r][c][fr][fc] == 0) continue;
     30         if(loop(fr, fc, i)) return true;
     31     }
     32     return false;
     33 }
     34 
     35 bool dfs(int id){
     36     if(id == finish) return true;
     37     if(id % N == 0) return dfs(id + 1); //该位置不做考虑,只是下一个位置的过渡
     38     int r = id / N, c = id % N;
     39     int jr = r + udr[0], jc = c + udc[0]; //判断该位置的数字是否大于0所用
     40     for(int i = 0; i < 2; i++){
     41         int ufr = r + udr[i], ufc = c + udc[i];
     42         int dfr = r + ddr[i], dfc = c + ddc[i];
     43         if(isdigit(grid[ufr][ufc]) && grid[ufr][ufc] - 1 < '0') continue;
     44         if(isdigit(grid[dfr][dfc]) && grid[dfr][dfc] - 1 < '0') continue;
     45         if(isdigit(grid[ufr][ufc])) grid[ufr][ufc]--;
     46         if(isdigit(grid[dfr][dfc])) grid[dfr][dfc]--;
     47         if(grid[jr][jc] > '0'){ //剪枝1
     48             renew(ufr, ufc, dfr, dfc);
     49             continue;
     50         }
     51         if(r == n){ //剪枝2
     52             int sr = r + ddr[1], sc = c + ddc[1];
     53             if(grid[sr][sc] > '0'){
     54                 renew(ufr, ufc, dfr, dfc);
     55                 continue;
     56             }
     57         }
     58         if(c == n){ //剪枝3
     59             int sr = r + udr[1], sc = c + udc[1];
     60             if(grid[sr][sc] > '0'){
     61                 renew(ufr, ufc, dfr, dfc);
     62                 continue;
     63             }
     64         }
     65         if(r == n && c == n){ //剪枝4
     66             int sr = r + ddr[0], sc = c + ddc[0];
     67             if(grid[sr][sc] > '0'){
     68                 renew(ufr, ufc, dfr, dfc);
     69                 continue;
     70             }
     71         }
     72         ans[r][c] = i;
     73         edge[ufr][ufc][dfr][dfc] = edge[dfr][dfc][ufr][ufc] = 1;
     74         mark++;
     75         if(loop(dfr, dfc, -1)){
     76             edge[ufr][ufc][dfr][dfc] = edge[dfr][dfc][ufr][ufc] = 0;
     77             renew(ufr, ufc, dfr, dfc);
     78             continue;
     79         }
     80         if(dfs(id + 1)) return true;
     81         edge[ufr][ufc][dfr][dfc] = edge[dfr][dfc][ufr][ufc] = 0;
     82         renew(ufr, ufc, dfr, dfc);
     83     }
     84     return false;
     85 }
     86 
     87 int main(){
     88     int T;
     89     scanf("%d", &T);
     90     while(T--){
     91         scanf("%d", &n);
     92         N = n + 1;
     93         for(int r = 1; r <= N; r++) scanf("%s", grid[r] + 1);
     94         memset(vis, 0, sizeof(vis));
     95         memset(edge, 0, sizeof(edge));
     96         mark = 1;
     97         finish = N * N;
     98         dfs(N + 1);
     99         for(int r = 1; r <= n; r++){
    100             for(int c = 1; c <= n; c++){
    101                 if(ans[r][c] == 0) printf("\");
    102                 else printf("/");
    103             }
    104             printf("
    ");
    105         }
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    不在折腾---hbase-0.96.2-hadoop2
    不在折腾---hive-0.13.1-bin
    不在折腾---storm-0.9.2-incubating分布式安装
    zookeeper的zoo.cfg的配置
    Linux常用命令
    不在折腾----zookeeper-3.4.5
    VMware克隆后,网卡若干问题
    防火墙基础技术-02
    JavaScript email格式校验
    js透明按钮图片滑动切换焦点图
  • 原文地址:https://www.cnblogs.com/hkxy125/p/7990863.html
Copyright © 2011-2022 走看看