zoukankan      html  css  js  c++  java
  • HZOJ 光

    一道大模拟,打的我要吐了。

    先说一下60%暴力吧,其实模拟光的路线即可,最好还是把边界设为障碍,这样就不用判边界了。最后输出n*m可以骗到10分。

    注意不要把n和m弄混(愁死我了)。

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<vector>
     5 #define LL long long
     6 #define int LL
     7 using namespace std;
     8 int n,m,k,xs,ys,f;
     9 char te[10];
    10 bool map[2010][2010];
    11 vector<short> v[1010][1010];
    12 void dfs(int x,int y,int num,int fx)
    13 {
    14 //    cout<<x<<" "<<y<<" "<<fx<<endl;
    15     if(v[x][y].size()==0)num++;
    16     for(int i=0;i<v[x][y].size();i++)if(v[x][y][i]==fx){cout<<num<<endl;exit(0);}
    17     v[x][y].push_back(fx);
    18     if(fx==1)
    19     {
    20         if(x==1&&y==m)dfs(x,y,num,3);
    21         else if(map[x-1][y]&&map[x-1][y+1]&&map[x][y+1])dfs(x,y,num,3);
    22         else if(x==1||(y<m&&map[x-1][y]&&map[x-1][y+1]))dfs(x,y+1,num,2);
    23         else if(y==m||(x>1&&map[x][y+1]&&map[x-1][y+1]))dfs(x-1,y,num,4);
    24         else if(map[x-1][y+1])dfs(x,y,num,3);
    25         else dfs(x-1,y+1,num,fx);
    26     }
    27     else if(fx==2)
    28     {
    29         if(x==n&&y==m)dfs(x,y,num,4);
    30         else if(map[x+1][y]&&map[x+1][y+1]&&map[x][y+1])dfs(x,y,num,4);
    31         else if(x==n||(y<m&&map[x+1][y]&&map[x+1][y+1]))dfs(x,y+1,num,1);
    32         else if(y==m||(x<n&&map[x][y+1]&&map[x+1][y+1]))dfs(x+1,y,num,3);
    33         else if(map[x+1][y+1])dfs(x,y,num,4);
    34         else dfs(x+1,y+1,num,fx);
    35     }//A
    36     else if(fx==3)
    37     {
    38         if(x==n&&y==1)dfs(x,y,num,1);
    39         else if(map[x+1][y]&&map[x+1][y-1]&&map[x][y-1])dfs(x,y,num,1);
    40         else if(x==n||(y>1&&map[x+1][y]&&map[x+1][y-1]))dfs(x,y-1,num,4);
    41         else if(y==1||(x<n&&map[x][y-1]&&map[x+1][y-1]))dfs(x+1,y,num,2);
    42         else if(map[x+1][y-1])dfs(x,y,num,1);
    43         else dfs(x+1,y-1,num,fx);
    44     }
    45     else if(fx==4)
    46     {
    47         if(x==1&&y==1)dfs(x,y,num,2);
    48         else if(map[x-1][y]&&map[x-1][y-1]&&map[x][y-1])dfs(x,y,num,2);
    49         else if(x==1||(y>1&&map[x-1][y]&&map[x-1][y-1]))dfs(x,y-1,num,3);
    50         else if(y==1||(x>1&&map[x][y-1]&&map[x-1][y-1]))dfs(x-1,y,num,1);
    51         else if(map[x-1][y-1])dfs(x,y,num,2);
    52         else dfs(x-1,y-1,num,fx);
    53     }
    54 }
    55 signed main()
    56 {
    57 //    freopen("ray0.in","r",stdin);
    58 
    59     cin>>n>>m>>k;
    60     if(n>1000||m>1000) {cout<<n*m<<endl;exit(0);}
    61     int a,b;
    62     for(int i=1;i<=k;i++)
    63     {
    64         cin>>a>>b;
    65         if(n<=1000&&m<=1000)map[a][b]=1;
    66     }
    67     cin>>xs>>ys>>te;
    68     for(int i=0;i<=m+1;i++)map[0][i]=map[n+1][i]=1;
    69     for(int i=0;i<=n+1;i++)map[i][0]=map[i][m+1]=1;
    70     if(te[0]=='N')
    71     {
    72         if(te[1]=='E')f=1;
    73         else f=4;//W
    74     }
    75     else//S
    76     {
    77         if(te[1]=='E')f=2;
    78         else f=3;//W
    79     }
    80     if(n<=1000&&m<=1000)
    81         dfs(xs,ys,0,f);
    82 }
    暴力

    然后说正解(其实就是优化了暴力):

    确实有点难以理解,对于光的路线,可以发现其实暴力中间枚举了很多无用的状态,怎么解决呢?

    有一个比较简单但是不好想的规律,对于斜线,x+y或x-y不变,那么我们就可以用这个数字代表一条斜线,对于每一条斜线开一个set,将这条斜线上的障碍的x插入,那么二分查找就可以实现快速地转移了。

    然而这样递归下去还是比较麻烦的,可以用循环。

    再说两个规律:光线经过的路径只可能是环而不是环+链(显然),一条路径中至多出现两次原路返回的情况(这个自己想想也不难,其实是我不会证)。

    所以循环处理即可,具体见代码。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<set>
      7 #include<map>
      8 #define LL long long
      9 #define MAXN 200010
     10 #define MP(a,b) make_pair(a,b)
     11 #define ma(x) memset(x,0,sizeof(x))
     12 using namespace std;
     13 int n,m,k;
     14 int xs,ys;char te[10];
     15 LL ans=0;
     16 struct rec{int x,y,d;};
     17 set<int> s1[MAXN],s2[MAXN];
     18 map<pair<int,int>,bool>mp;
     19 int getid(int x,int y,int d){return d==1?x-y+m+1:x+y;}
     20 bool same(rec a,rec b){if(a.x==b.x&&a.y==b.y&&a.d==b.d)return 1;return 0;}
     21 bool check(int x,int y){return mp[MP(x,y)];}
     22 void add(int x,int y)
     23 {
     24     s1[getid(x,y,1)].insert(x);
     25     s2[getid(x,y,2)].insert(x);
     26     mp[MP(x,y)]=1;
     27 }
     28 pair<rec,int> dfs(rec u)
     29 {
     30     rec re;
     31     set<int>::iterator it;
     32     if(u.d==1)
     33     {
     34         it=s1[getid(u.x,u.y,1)].lower_bound(u.x);it--;
     35         re.x=u.x-(abs(*it-u.x)-1);
     36         re.y=u.y-(abs(*it-u.x)-1);
     37         if(check(re.x-1,re.y)&&check(re.x,re.y-1))re.d=3;
     38         else if(check(re.x-1,re.y))re.d=4,re.y--;
     39         else if(check(re.x,re.y-1))re.d=2,re.x--;
     40         else re.d=3;
     41     }
     42     if(u.d==2)
     43     {
     44         it=s2[getid(u.x,u.y,2)].lower_bound(u.x);it--;
     45         re.x=u.x-(abs(*it-u.x)-1);
     46         re.y=u.y+(abs(*it-u.x)-1);
     47         
     48         if(check(re.x-1,re.y)&&check(re.x,re.y+1))re.d=4;
     49         else if(check(re.x-1,re.y))re.d=3,re.y++;
     50         else if(check(re.x,re.y+1))re.d=1,re.x--;
     51         else re.d=4;
     52     }
     53     if(u.d==3)
     54     {
     55         it=s1[getid(u.x,u.y,1)].lower_bound(u.x);
     56         re.x=u.x+(abs(*it-u.x)-1);
     57         re.y=u.y+(abs(*it-u.x)-1);
     58         
     59         if(check(re.x+1,re.y)&&check(re.x,re.y+1))re.d=1;
     60         else if(check(re.x+1,re.y))re.d=2,re.y++;
     61         else if(check(re.x,re.y+1))re.d=4,re.x++;
     62         else re.d=1;        
     63     }
     64     if(u.d==4)
     65     {
     66         it=s2[getid(u.x,u.y,2)].lower_bound(u.x);
     67         re.x=u.x+(abs(*it-u.x)-1);
     68         re.y=u.y-(abs(*it-u.x)-1);
     69         
     70         if(check(re.x+1,re.y)&&check(re.x,re.y-1))re.d=2;
     71         else if(check(re.x+1,re.y))re.d=1,re.y--;
     72         else if(check(re.x,re.y-1))re.d=3,re.x++;
     73         else re.d=2;        
     74     }    
     75     return MP(re,abs(*it-u.x));
     76 }
     77 bool judge(rec u)
     78 {
     79     rec re=u;
     80     do
     81     {
     82         pair<rec,int> cur=dfs(u);
     83         ans+=cur.second;
     84         switch(cur.first.d)    
     85         {
     86             case 1:if(u.d==3)return 0;break;
     87             case 2:if(u.d==4)return 0;break;
     88             case 3:if(u.d==1)return 0;break;
     89             case 4:if(u.d==2)return 0;break;
     90         }
     91         u=cur.first;
     92     }while(!same(re,u));
     93     return 1;
     94 }
     95 
     96 signed main()
     97 {
     98 //    freopen("in.txt","r",stdin);
     99 
    100     cin>>n>>m>>k;
    101     for(int i=0;i<=m+1;i++)add(0,i),add(n+1,i);
    102     for(int i=1;i<=n;i++)  add(i,0),add(i,m+1);
    103     int a,b;
    104     for(int i=1;i<=k;i++)
    105     {
    106         cin>>a>>b;
    107         add(a,b);
    108     }
    109     int f;
    110     cin>>xs>>ys>>te;
    111     if(te[0]=='N')
    112     {
    113         if(te[1]=='E')f=2;
    114         else f=1;//W
    115     }
    116     else//S
    117     {
    118         if(te[1]=='E')f=3;
    119         else f=4;//W
    120     }
    121     rec st={xs,ys,f};
    122     st=dfs(st).first;
    123     if(!judge(st))//判断第一次反向
    124     {
    125         ans--;
    126         switch(st.d)
    127         {
    128             case 1:st.d=3;break;
    129             case 2:st.d=4;break;
    130             case 3:st.d=1;break;
    131             case 4:st.d=2;break;
    132         }    
    133         judge(st);
    134     }
    135     cerr<<ans<<endl;
    136     cout<<ans<<endl;
    137 }
  • 相关阅读:
    HeidiSQL 导入Excel数据
    两片74门实现的双边沿D触发器
    java多线程
    java集合框架
    java异常处理
    java基础学习5
    java基础学习4
    Java基础学习3
    Java基础学习2
    LeetCode 184场周赛
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11228421.html
Copyright © 2011-2022 走看看