设为首页 加入收藏

TOP

bzoj 3519: [Zjoi2014] 消棋子 题解
2015-07-24 05:55:36 来源: 作者: 【 】 浏览:9
Tags:bzoj 3519: Zjoi2014 棋子 题解

【序言】在大家怀疑的眼光下,我做了一个中午和半个下午、调了一个晚上的题目总算A了!

【原题】

消棋子是一个有趣的游戏。游戏在一个r * c的棋盘上进行。棋盘的每个格

子,要么是空,要么是一种颜色的棋子。同一种颜色的棋子恰好有两个。每一轮,
玩家可以选择一个空格子(x, y),并选择上下左右四个方向中的两个方向,如果
在这两个方向上均存在有棋子的格子,而且沿着这两个方向上第一个遇到的棋子
颜色相同,那么,我们将这两个棋子拿走,并称之为合法的操作。否则称这个操
作不合法,游戏不会处理这个操作。游戏的目的是消除尽量多的棋子。
给出这样一个游戏和一个人的玩法。你需要:
z 指出此人能消去多少棋子。
z 给出一种能消去最多棋子的方案。
【输入格式】
在输入文件eliminate.in中,第一行给出了整数r, c。第二行给出了整数n,
表示不同颜色数。接下来n行,第i行含4个整数a[i], b[i], c[i], d[i],表示颜色
为i的两个格子分别是(a[i], b[i]), (c[i], d[i])。然后是一个整数m,表示此人的操
作数。接下来m行,每行有2个整数和2个字母,代表了他选择的格子,以及
两个方向。我们用“UDLR”分别表示上下左右。
【输出格式】
在输出文件eliminate.out中,第一行输出此人能消去多少棋子。第二行含一
个整数k(0 ≤k ≤10
6
),表示你给出的方案的操作数。接下来k行,每行2个整数和
2个字母,代表你选择的格子以及两个方向。
【样例输入】
4 4
4
1 1 1 4
1 2 3 4
1 3 3 2
4 1 2 3
6
2 3 U R
2 1 D R
2 2 L R
2 4 L D
3 1 L R
3 3 L U

【样例】

\

【分析】开始感觉思路还是挺简单的,但是代码写起来真的是越写越长。。。

我的基本思路是用set维护相邻的情况,有点像前几天做的那道Garden。对于每一个横行和每一个竖列分别开一个set,表示这一横行和竖列上的坐标。每次的操作都是基于lower_bound的。

首先考虑读入的那个人。显然这个很简单(代码23行),直接模拟即可。比如我们要消掉这样一对棋子。

\

设左上角(x1,y1),右下角(x2,y2)。我们可以把x1所在的set里的y1删掉,把y1所在的set里的x1删掉,对于x2,y2也如此。每次判断一对点中间路线上是否还有棋子并删除点。<??http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+wum3s7XEu7nKx9fu08UmIzIwNTQwO6Os1vfSqrXEwum3s9autKbU2tPat9bA4MzWwtuhozwvcD4KPHA+z8iw0daxvdPE3Mm+tcS3xcjrttPB0NbQo6zIu7rzw7+0zsTDs/bG5NbQ0ru21LXjoaPPyMm+tfTV4rbUteOjrMi7uvPF0LbP0rvPwtXittS147i9vfzKx7fx09DExLbUtePS8s6qyb6z/cHL1eK21LXjtvjSsr/J0tTJvrP9wcujrM2syrHI67bToaPXotLi0rvPwrXE0rvQqc+4vdqhozwvcD4KPHA+otnEs9K7teO/ycTcu+HI67bTusO8uLTOo6zS8rTL0qrTw2ZsYWe8x8K80rvPwqGjPC9wPgo8cD6i2rK70qrN/LzHzNjF0HgxPXgyus15MT15MrXEx+m/9qGjPC9wPgo8cD6i28/UyLvDtr7ZtcTKxyh4MSx5MSm6zSh4Mix5MinLxNbcuf3IpbXEtdrSu7j2teOho7WrysfXotLi1rvKx7K7ubu1xKOsu7nT0Ch4MSx5Mim6zSh4Mix5MSmhozwvcD4KPHA+otzV4tK7tePX7r/Twcujodei0uKjrGxvd2VyX2JvdW5ky9Gyu7W9tcTIt7vht7W72GVuZCgpo6y1q8rH1NplcmFzZaGiZmluZLXItcTKsbryo6zI57n7w7vT0MzYxdDKubT4vfjIpbXEaXRlcmF0b3K78sr9JiMyMDU0MDuyu7bUo6y74bGstfS1xKGjuNXQtM3quvPO0r7N0rvWsVJFoaM8L3A+CjxwPsi7uvPO0r7Nv6rKvML+s6S1xLX3s8zQ8tauwsPBy6Gj0tG+rdPQtePN/Mi0xMTA77eiyfrBy7TtzvOjrLWryse3tNX9s8zQ8tS9vNPUvbOko6jL5Mi70NDK/bK7yse63Lbgo6mho8Wqtb2688C0o6y007bUMbj2teO1vTO49rXj1Nm1vTW49rXjo6zWrrrztrzKx7Tzyv2+3cHLoaM8L3A+CjxwPtPayse+zb+qyry21MXEoaPOqsHLt72x46OsztLWu8XE1+7TxSYjMjA1NDA7tcTH6b/2oaM8L3A+CjxwPqG+1OzK/b7ds8zQ8qG/PC9wPgo8cD48cHJlIGNsYXNzPQ=="brush:java;">#include #include #include using namespace std; bool f[40005][40005];int x1,y1,x2,y2; int main() { freopen("eliminate.in","w",stdout); srand((int)time(0)); int r=10,c=10; printf("%d %d\n",r,c); int n=5; printf("%d\n",n); for (int i=1;i<=n;i++) { while (1) { x1=rand()%r+1;y1=rand()%c+1;x2=rand()%r+1;y2=rand()%c+1; if (!f[x1][y1]&&!f[x2][y2]&&(x1!=x2||y1!=y2)) break; } printf("%d %d %d %d\n",x1,y1,x2,y2); f[x1][y1]=f[x2][y2]=1; } }

真的要好好感谢我的造数据程序。首先是发现了x1==x2特判的时候有点问题。之后就过了8个点,然后剩下的两个最大的点就一直错误,而且答案相差仅一点点!!然后我只好再次无奈的对拍,大约20分钟后拍出了n==5的错误。

一下是错点图片:

\ 后来才发现,iterator的指针基本每个函数都有,还开了全局变量。这样,Find里的iterator因为执行了一个check过程而有微小的变化。数据真的是太厉害了!

【代码】

#include
  
   
#include
   
     #include
    
      #include
      #define N 100005 using namespace std; map
      
       prex[N],prey[N]; multiset
       
        P[N],Q[N],X[N],Y[N]; typedef multiset
        
         ::iterator It; It it1,it2,it; int m,n,r,c,h,t,x,y,x1,x2,y1,y2,i,wri[N][2],id[N][4],flag[N]; char re[N][2]; void Person() { scanf("%d",&m);int ans=0,c[2];char s1[2],s2[2];It it[2]; while (m--) { scanf("%d%d%s%s",&x,&y,&s1,&s2); if (P[x].find(y)!=P[x].end()) continue; int o=0,tx,ty;It it[2];c[0]=-1;c[1]=-2; if (s1[0]=='U'||s2[0]=='U') {it[o]=Q[y].lower_bound(x);if (it[o]==Q[y].begin()) continue;c[o]=prey[y][*(--it[o])];o++;} if (s1[0]=='L'||s2[0]=='L') {it[o]=P[x].lower_bound(y);if (it[o]==P[x].begin()) continue;c[o]=prex[x][*(--it[o])];o++;} if (s1[0]=='D'||s2[0]=='D') {it[o]=Q[y].lower_bound(x);if (it[o]==Q[y].end()) continue;c[o]=prey[y][*it[o]];o++;} if (s1[0]=='R'||s2[0]=='R') {it[o]=P[x].lower_bound(y);if (it[o]==P[x].end()) continue;c[o]=prex[x][*it[o]];o++;} if (c[0]!=c[1]) continue; ans+=1;o=0; if (s1[0]=='U'||s2[0]=='U') {tx=*it[o];Q[y].erase(it[o]);P[tx].erase(P[tx].find(y));o++;} if (s1[0]=='L'||s2[0]=='L') {ty=*it[o];P[x].erase(it[o]);Q[ty].erase(Q[ty].find(x));o++;} if (s1[0]=='D'||s2[0]=='D') {tx=*it[o];Q[y].erase(it[o]);P[tx].erase(P[tx].find(y));o++;} if (s1[0]=='R'||s2[0]=='R') {ty=*it[o];P[x].erase(it[o]);Q[ty].erase(Q[ty].find(x));o++;} } printf("%d ",ans); } void y1_s_y2(int num) { if (flag[num]) return; it1=X[x1].upper_bound(y1);it2=Y[y2].lower_bound(x1); if ((*it1>y2||it1==X[x1].end())&&*it2==x2) {re[++t][0]='L';re[t][1]='D';wri[t][0]=x1;wri[t][1]=y2;flag[num]=1;return;} it1=Y[y1].upper_bound(x1);it2=X[x2].lower_bound(y1); if ((*it1>x2||it1==Y[y1].end())&&*it2==y2) {re[++t][0]='R';re[t][1]='U';wri[t][0]=x2;wri[t][1]=y1;flag[num]=1;} } void y1_b_y2(int num) { if (flag[num]) return; it1=Y[y1].upper_bound(x1);it2=X[x2].upper_bound(y2); if ((*it1>x2||it1==Y[y1].end())&&(*it2>y1||it2==X[x2].end())) {re[++t][0]='L';re[t][1]='U';wri[t][0]=x2;wri[t][1]=y1;flag[num]=1;return;} it1=X[x1].lower_bound(y2); it2=Y[y2].lower_bound(x1); if (*it1==y1&&*it2==x2) {re[++t][0]='R';re[t][1]='D';wri[t][0]=x1;wri[t][1]=y2;flag[num]=1;} } void x1_e_x2(int num) { if (flag[num]) return; if (y1>y2) swap(y1,y2);It it=X[x1].upper_bound(y1);if ((*it)
         
          x2) swap(x1,x2),swap(y1,y2);int o=0; if (x1==x2) {x1_e_x2(num);return;} if (y1==y2) y1_e_y2(num); if (y1
          
           y2) y1_b_y2(num); } void DO(int x,int y) { It dd=Y[y].lower_bound(x);int fd=dd==Y[y].end(); It rr=X[x].lower_bound(y);int fr=rr==X[x].end(); It uu=dd;int fu=(uu==Y[y].begin());if (!fu) uu--; It ll=rr;int fl=(ll==X[x].begin());if (!fl) ll--; int d=*dd,r=*rr,u=*uu,l=*ll; if (!fd) check(d,y); if (!fu) check(u,y); if (!fl) check(x,l); if (!fr) check(x,r); } void Find() { int G1,G2; for (int i=1;i<=n;i++) { x1=id[i][0]; y1=id[i][1]; check(x1,y1); } while (h
           
            

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇LeetCode:Roman to Integer,Integ.. 下一篇HDU4417-Super Mario

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: