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 }

 

posted @ 2019-07-23 21:20  Al_Ca  阅读(178)  评论(0编辑  收藏  举报
ヾ(≧O≦)〃嗷~