ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[ZJOI 2005] 梦幻折纸

2019-03-29 17:39:27  阅读:353  来源: 互联网

标签:const int 格线 stk return 折纸 2005 ZJOI ref


题目传送-Luogu

题意:

给一个 \(n*m\) 的网格图,每个网格上有 \([1,n*m]\) 的数字,且每个都出现且恰好出现一次.
显然进行若干次折叠直到剩下一个 \(1*1\) 的小网格时,它在纵向上有 \(n*m\) 层.
那么能否安排一种折叠方案,使得这 \(n*m\) 层从上往下的标号恰好为 \(1\) 到 \(n*m\).

题解:

显然每个纵向和横向的格线都会被折到.我们观察剩下的的那个小方格,可以发现每层都有向左或右,上或下的连接,而且上下的连接和左右的连接是无关的.
然而还是没有什么卵用...
这时我们考虑什么情况下会不存在合法的方案,先举个例子:1 3 4 2.
我们想象面前有个 \(1*4\) 的纸条,先把 3 折到 1 的下面,再把 4 折到 3 的下面,这时我们发现 2 居然折不进去了.
这是因为 \(4,2\) 和 \(1,3\) 的连接是同向的,那么这样就不能交叉进去了.
那么我们发现折痕的方向是相邻的格线两两相反的(折一折就知道了)
根据上面的结论,相同的方向的折痕不能存在相交.这样我们就会只有一条的情况了.

对于一般情况,我们发现当一条格线被决策后,它所在的所有格子都会被强制决策.
由于行和列是互不影响的,那么这个就很好扩展了.

过程:

想了超级久的..

代码:

#define GG {puts("Cheat"); continue;}
const int N=110;
int n,m;
int G[N][N];
struct SEG {
  int L,R;
  inline void Config() {
    if(L>R) swap(L,R);
  }
  inline void Print() {
    printf("%d %d\n",L,R);
  }
  bool operator < (const SEG &a)const {
    return L<a.L;
  }
};
vector<SEG> seg[2];
inline bool Judge() {
  //printf("Start\n");
  for(int t=0;t<2;t++) {
    sort(seg[t].begin(),seg[t].end());
    //for(int i=0;i<(int)seg[t].size();i++) seg[t][i].Print();
    vector<pii> ref;
    for(int i=0;i<(int)seg[t].size();i++) {
      ref.pb(mp(seg[t][i].L,i+1));
      ref.pb(mp(seg[t][i].R,-i-1));
    }
    sort(ref.begin(),ref.end());
    assert(ref.size()==seg[t].size()*2);
    stack<int> stk;
    for(int i=0;i<(int)ref.size();i++) {
      //printf("Ask::%d %d\n",ref[i].F,ref[i].S);
      if(ref[i].S>0) stk.push(ref[i].S);
      else {
    if(stk.top()!=-ref[i].S) return false;
    stk.pop();
      }
    }
  }
  return true;
}
signed main() {
  int T; read(T);
  for(int cas=1;cas<=T;cas++) {
    read(n); read(m);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
    read(G[i][j]);
    seg[0].clear(); seg[1].clear();
    for(int i=1;i<n;i++)
      for(int j=1;j<=m;j++)
    seg[i&1].pb((SEG){G[i][j],G[i+1][j]});
    for(int i=0;i<2;i++)
      for(int j=0;j<(int)seg[i].size();j++)
    seg[i][j].Config();
    if(!Judge()) GG;

    seg[0].clear(); seg[1].clear();
    for(int j=1;j<m;j++)
      for(int i=1;i<=n;i++)
    seg[j&1].pb((SEG){G[i][j],G[i][j+1]});
    for(int i=0;i<2;i++)
      for(int j=0;j<(int)seg[i].size();j++)
    seg[i][j].Config();
    if(!Judge()) GG;
    puts("AllRight");
  }
  return 0;
}

用时: \(\infty\)

标签:const,int,格线,stk,return,折纸,2005,ZJOI,ref
来源: https://www.cnblogs.com/functionendless/p/10622780.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有