zoukankan      html  css  js  c++  java
  • Codeforces Round #292 (Div. 2) D. Drazil and Tiles [拓扑排序 dfs]

    传送门

    D. Drazil and Tiles
    time limit per test 2 seconds
    memory limit per test 256 megabytes

    Drazil created a following problem about putting 1 × 2 tiles into an n × m grid:

    "There is a grid with some cells that are empty and some cells that are occupied. You should use1 × 2 tiles to cover all empty cells and no two tiles should cover each other. And you should print a solution about how to do it."

    But Drazil doesn't like to write special checking program for this task. His friend, Varda advised him: "how about asking contestant only to print the solutionwhen it exists and it is unique? Otherwise contestant may print 'Not unique' ".

    Drazil found that the constraints for this task may be much larger than for the original task!

    Can you solve this new problem?

    Note that you should print 'Not unique' either when there exists no solution or when there exists several different solutions for the original task.

    Input

    The first line contains two integers n and m (1 ≤ n, m ≤ 2000).

    The following n lines describe the grid rows. Character '.' denotes an empty cell, and the character '*' denotes a cell that is occupied.

    Output

    If there is no solution or the solution is not unique, you should print the string "Not unique".

    Otherwise you should print how to cover all empty cells with1 × 2 tiles. Use characters "<>" to denote horizontal tiles and characters "^v" to denote vertical tiles. Refer to the sample test for the output format example.

    Sample test(s)
    Input
    3 3
    ...
    .*.
    ...
    
    Output
    Not unique
    
    Input
    4 4
    ..**
    *...
    *.**
    ....
    
    Output
    <>**
    *^<>
    *v**
    <><>
    
    Input
    2 4
    *..*
    ....
    
    Output
    *<>*
    <><>
    
    Input
    1 1
    .
    
    Output
    Not unique
    
    Input
    1 1
    *
    
    Output
    *
    
    Note

    In the first case, there are indeed two solutions:

    <>^
    ^*v
    v<>
    

    and

    ^<>
    v*^
    <>v
    

    so the answer is "Not unique".

    题意及题解转自田神:http://blog.csdn.net/tc_to_top/article/details/43876015

    题目大意:n*m的矩阵,' . '表示位置空,' * '表示障碍物,问能不能用尖括号填满空的点,使矩阵中所有的尖括号都两两配对,水平配对:<> 竖直配对:^v,若不存在或答案不唯一输出Not unique

    题目分析:有趣的题,DFS搜索,策略:先把*的点的数量记下来,每次向四周扩展时先找只有一个方向可扩展的点扩展,因为它的灵活度最小,也就是说在它这的策略是唯一的,每个点都搜一次,最后如果n * m = cnt表示每个点都填满了(包括障碍物)则说明有且只有一解

    这题还可以用拓扑排序,而不是dfs,第一份代码是我的拓扑排序,第二份是田神的dfs,结果dfs还要快,晕= =

    9954592 2015-02-22 04:53:19 njczy2010 D - Drazil and Tiles GNU C++ Accepted 233 ms 26400 KB 
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<queue>
      8 #include<map>
      9 #include<set>
     10 #include<stack>
     11 #include<string>
     12 
     13 #define N 2010
     14 #define M 10005
     15 //#define mod 10000007
     16 //#define p 10000007
     17 #define mod2 1000000000
     18 #define ll long long
     19 #define ull unsigned long long
     20 #define LL long long
     21 #define eps 1e-6
     22 //#define inf 2147483647
     23 #define maxi(a,b) (a)>(b)? (a) : (b)
     24 #define mini(a,b) (a)<(b)? (a) : (b)
     25 
     26 using namespace std;
     27 
     28 int n;
     29 int m;
     30 char s[N][N];
     31 int r[N][N];
     32 int dirx[]={1,0,-1,0};          //d,r,u,l
     33 int diry[]={0,1,0,-1};
     34 int tot;
     35 
     36 typedef struct
     37 {
     38     int x;
     39     int y;
     40 }PP;
     41 
     42 int calr(int x,int y)
     43 {
     44     r[x][y]=0;
     45     int dir;
     46     if(s[x][y]!='.') return -1;
     47     int i;
     48     int nx,ny;
     49     for(i=0;i<4;i++){
     50         nx=x+dirx[i];
     51         ny=y+diry[i];
     52         if(s[nx][ny]=='.'){
     53             r[x][y]++;
     54             dir=i;
     55         }
     56     }
     57     return dir;
     58 }
     59 
     60 void ini()
     61 {
     62     int i,j;
     63     memset(r,0,sizeof(r));
     64     for(i=0;i<=n+1;i++){
     65         for(j=0;j<=m+1;j++){
     66             s[i][j]=0;
     67         }
     68     }
     69     for(i=1;i<=n;i++){
     70         scanf("%s",s[i]+1);
     71     }
     72     tot=0;
     73 }
     74 
     75 void solve()
     76 {
     77     queue<PP>q;
     78     int i,j;
     79     PP te,nt,ntt;
     80     int dir;
     81     for(i=1;i<=n;i++){
     82         for(j=1;j<=m;j++){
     83             if(s[i][j]=='*'){
     84                 tot++;continue;
     85             }
     86             calr(i,j);
     87             te.x=i;te.y=j;
     88             if(r[i][j]==1){
     89                 q.push(te);
     90             }
     91         }
     92     }
     93     while(q.size()>=1)
     94     {
     95         te=q.front();
     96         q.pop();
     97         dir=calr(te.x,te.y);
     98         if(r[te.x][te.y]!=1) continue;
     99         nt.x=te.x+dirx[ dir ];
    100         nt.y=te.y+diry[ dir ];
    101         tot+=2;
    102         if(dir==0){
    103             s[te.x][te.y]='^';s[nt.x][nt.y]='v';
    104         }
    105         else if(dir==2){
    106             s[te.x][te.y]='v';s[nt.x][nt.y]='^';
    107         }
    108         else if(dir==1){
    109             s[te.x][te.y]='<';s[nt.x][nt.y]='>';
    110         }
    111         else if(dir==3){
    112             s[te.x][te.y]='>';s[nt.x][nt.y]='<';
    113         }
    114         for(j=0;j<4;j++){
    115             ntt.x=nt.x+dirx[j];
    116             ntt.y=nt.y+diry[j];
    117             calr(ntt.x,ntt.y);
    118             if(r[ntt.x][ntt.y]==1){
    119                 q.push(ntt);
    120             }
    121         }
    122     }
    123 }
    124 
    125 void out()
    126 {
    127     if(tot!=n*m){
    128         printf("Not unique
    ");
    129     }
    130     else{
    131         int i;
    132         for(i=1;i<=n;i++){
    133             printf("%s
    ",s[i]+1);
    134         }
    135     }
    136 }
    137 
    138 int main()
    139 {
    140     //freopen("data.in","r",stdin);
    141     //freopen("data.out","w",stdout);
    142     //scanf("%d",&T);
    143     //for(int ccnt=1;ccnt<=T;ccnt++)
    144     //while(T--)
    145     //scanf("%d%d",&n,&m);
    146     while(scanf("%d%d",&n,&m)!=EOF)
    147     {
    148         ini();
    149         solve();
    150         out();
    151     }
    152     return 0;
    153 }

    下面转一下田神的dfs:

    9954596 2015-02-22 04:54:37 njczy2010 D - Drazil and Tiles GNU C++ Accepted 155 ms 4056 KB
     1 #include <cstdio>
     2 #include <cstring>
     3 int const MAX = 2005;
     4 char s[MAX][MAX];
     5 int n, m, cnt;
     6 int dx[4] = {0, 0, 1, -1};
     7 int dy[4] = {1, -1, 0, 0};
     8 
     9 void dfs(int x, int y)
    10 {
    11     if(x < 1 || x > n || y < 1 || y > m || s[x][y] != '.')
    12         return;
    13     int dir = -1, sum = 0;
    14     for(int i = 0; i < 4; i++)
    15     {
    16         int xx = x + dx[i];
    17         int yy = y + dy[i];
    18         if(s[xx][yy] == '.')
    19         {
    20             sum ++;
    21             dir = i;
    22         }
    23     }
    24     if(sum == 1)  //保证解的唯一性
    25     {
    26         if(dir == 0)
    27         {
    28             s[x][y] = '<';
    29             s[x][y + 1] = '>';
    30         }
    31         else if(dir == 1)
    32         {
    33             s[x][y] = '>';
    34             s[x][y - 1] = '<';
    35         }
    36         else if(dir == 2)
    37         {
    38             s[x][y] = '^';
    39             s[x + 1][y] = 'v';
    40         }
    41         else if(dir == 3)
    42         {
    43             s[x][y] = 'v';
    44             s[x - 1][y] = '^';
    45         }
    46         cnt += 2;
    47         for(int i = 0; i < 4; i++)
    48             dfs(x + dx[dir] + dx[i], y + dy[dir] + dy[i]);
    49     }
    50 }
    51 
    52 int main()
    53 {
    54     cnt = 0;
    55     scanf("%d %d", &n, &m);
    56     for(int i = 1; i <= n; i++)
    57         scanf("%s", s[i] + 1);
    58     for(int i = 1; i <= n; i++)
    59         for(int j = 1; j <= m; j++)
    60             if(s[i][j] == '*')
    61                 cnt ++;
    62     for(int i = 1; i <= n; i++)
    63         for(int j = 1; j <= m; j++)
    64             dfs(i, j);
    65     if(cnt == n * m)
    66         for(int i = 1; i <= n; i++)
    67             printf("%s
    ", s[i] + 1);
    68     else
    69         printf("Not unique
    ");
    70 }
  • 相关阅读:
    Kali-linux物理访问攻击
    Kali-linux使用NVIDIA计算机统一设备架构(CUDA)
    Kali-linux创建密码字典
    Kali-linux破解操作系统用户密码
    Kali-linux破解纯文本密码工具mimikatz
    Kali-linux绕过Utilman登录
    POJ
    LightOJ
    UVa
    Hdu
  • 原文地址:https://www.cnblogs.com/njczy2010/p/4297322.html
Copyright © 2011-2022 走看看