首页 > 其他分享 >ABC336 F Rotation Puzzle 题解

ABC336 F Rotation Puzzle 题解

时间:2024-01-16 10:12:31浏览次数:32  
标签:int 题解 Puzzle vee mp2 ans 操作 Rotation now

Question

ABC336 F Rotation Puzzle

给出一个 \(H\times W\) 的矩阵,里面填有数字,有一种操作

  • 选定一个 \((x,y)\) 交换 \((i+x,j+y)\) 和 \((H-i+x,W-j+y)\) 对于每一个 \(1\le i \le H-1,1\le j \le W-1\)

问,是否能经过 \(20\) 次以内的操作使得,最后的矩形变成 \((i,j)=((i-1)\times W+j)\)

Solution

观察发现 \((i,j)=((i-1)\times W+j)\) 就是 \(1,2,3,\cdots\) 这样子下来

image.png

然后操作就是选一个顶点 \((x,y)\) 然后对于 \((H-1)\times (W-1)\) 的矩阵进行一次 "翻转" 操作

image.png

每次可以翻转的有四个选择 \((x,y)=(0,1),(1,0),(0,0),(1,1)\)

考虑暴力搜索,复杂度为 \(4^{20}=1099511627776\)

显然不符合,然后考虑折半搜索 \(4^{10}=1048576\),复杂度降下来了,但是还是会超时

考虑到搜索的过程中有很多的重复元素,例如经过一次 \((0,0)\) 操作后再进行一次 \((0,0)\) 操作就没有意义了,所以有意义的操作次数是 \(3^{10}=59049\) ,用 BFS 比较实现去重

之后就是把一个矩阵对应一个数,对应到达这个矩阵状态的操作次数,从起点做一次 BFS,从终点做一次 BFS(就是折半枚举的常规操作)

Code

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long LL;
typedef vector<vector<int> > vee;
int n,m,ans=INF;
map<vee,int> mp1,mp2;

void F(int x,int y,vee& now){
    int cnt=0;
    for(int i=1;i<=(n-1);i++)
    for(int j=1;j<=(m-1);j++){
        swap(now[i+x][j+y],now[n-i+x][m-j+y]);
        if(++cnt>=(n-1)*(m-1)/2) return ;
    }
}

void bfs1(vee a){
    queue<vee> q;q.push(a);mp1[a]=0;
    while(!q.empty()){
        vee now=q.front(); q.pop();
        int stp=mp1[now];
        if(stp>=10) return;
        for(int x=0;x<=1;x++)
        for(int y=0;y<=1;y++){
            vee nxt=now;
            F(x,y,nxt);
            if(mp1.find(nxt)==mp1.end()){
                mp1[nxt]=stp+1;
                q.push(nxt);
            }
        }
    }
}

void bfs2(vee a){
    queue<vee> q;q.push(a);
    mp2[a]=0;
    while(!q.empty()){
        vee now=q.front(); q.pop();
        int stp=mp2[now];
        if(stp>=10) return;
        for(int x=0;x<=1;x++)
        for(int y=0;y<=1;y++){
            vee nxt=now;
            F(x,y,nxt);
            if(mp2.find(nxt)==mp2.end()){
                mp2[nxt]=stp+1;
                q.push(nxt);
            }
        }
    }
}

int main(){
    freopen("F.in","r",stdin);
    vee st;
    scanf("%d%d",&n,&m);
    st.assign(n+1,vector<int>(m+1,0));
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&st[i][j]);
    bfs1(st);

    int tot=0;vee ed(n+1,vector<int>(m+1,0));
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) ed[i][j]=++tot;
    bfs2(ed);

    for(auto it=mp1.begin();it!=mp1.end();++it){
        if(mp2.find(it->first)!=mp2.end())
            ans=min(ans,it->second+mp2[it->first]);
    }

    if(ans==INF||ans>20)
        printf("-1\n");
    else 
        printf("%d\n",ans);
    return 0;
}

标签:int,题解,Puzzle,vee,mp2,ans,操作,Rotation,now
From: https://www.cnblogs.com/martian148/p/17967014

相关文章

  • P1002题解
    思路设\(dp_{i,j}\)表示第\(i\)行\(j\)列卒走到这里有多少种方式。卒是可以向右和下走,所以到这个点只能从左或上来,不难得出转移公式:\(dp_{i,j}=dp_{i-1,j}+dp_{i,j-1}\)。如果马在这个点上或者说马能到这个点上,那么卒不能到这个点,也就是卒到这个点的方式为\(0\)。如......
  • P1003题解
    简单模拟题。思路枚举每一个地毯,因为后面的会覆盖前面的,所以从正序枚举。如果要求的点的坐标在当前地毯上,则将答案赋值为当前地毯编号。最后输出答案。那如果这个点没有地毯呢?答案初始设为\(-1\),这样没有地毯覆盖的话,答案不会改变,这样输出答案就会是\(-1\)。注意:记得赋初......
  • P10058题解
    怎么前三题都是思维题啊。思路总共有三个操作,先不看翻转操作。如果你右移\(x\)位之后,左移\(x\)位,那么就相当于没有操作。这个应该是很好理解的。我们根据上面的结论,能得出以下代码。if(op==">"){cin>>x;f+=x;}elseif(op=="<"){......
  • CF1409D题解
    思路因为数据较大,使用字符串读入。考虑使用贪心。先统计出当前数码之和。然后从低位往高位枚举,看一下把当前位改了之后是否小于等于\(s\)。如果小于的话,则统计出把当前位往后所有位都改为0,\(k\)为多少,求出的\(k\)就是最优解。说明一下为什么要从低位往高位枚举,这样如果成......
  • AT_arc060_c题解
    纪念模拟考考挂。思路首先二分查找出当前点往后走最远能去哪个点,当前点为\(i\),记最远能去的那个点为\(nt_i\)。考虑建一棵树,将\(nt_i\)设为\(i\)点的父节点。暴力的话直接从当前点往上找,找到目标节点看几次就好了。但显然是过不了的。考虑使用倍增优化。设\(g_{i,j}......
  • 1.15模拟赛 T2题解
    简要题意多重背包但是乘法思路暴力就直接跑背包考虑乘法能否变为加法,可以找到模数的原根,将每个数映射一下,这样乘法就变成了加法,可以直接\(\text{bitset}\)优化,但是暴力这样做还是过不了于是我们考虑二进制分组优化背包,这样复杂度貌似就对了?code#pragmaGCCoptimize("Ofast......
  • border设置渐变boder-radius不生效问题解决方案
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metahttp-equiv="X-UA-Compatible"content="IE=edge"/><metaname="viewport"c......
  • 【题解】gym103743 (2022 JSCPC)
    A.PENTAKILL!考虑直接模拟,规则就是一个人将其他人全部都击杀,并且中间没有重复击杀。code:#include<bits/stdc++.h>usingnamespacestd;map<string,vector<string>>st;intn;stringa,b;intmain(){cin>>n;for(inti=1;i<=n;++i){ci......
  • 题解「JOI 2014 Final」IOI 馒头
    传送门。题意有\(n\)个物品,\(m\)个背包。第\(i\)个物品的价值是\(P_i\),第\(j\)个背包可以装\(C_i\)个物品,但会消耗\(E_i\)的价值。背包不能重复买,问最多可以获得多少价值。分析首先一个简单的贪心,我们在购买背包后塞入物品,一定时从大往小塞,也就是说,我们可以先对......
  • abc336 E - Digit Sum Divisible 题解 数位DP
    题目链接:https://atcoder.jp/contests/abc336/tasks/abc336_e题目大意:我们定义一个整数\(n\)的数位和为\(n\)的十进制表示中的各位上的数字之和。比如:整数\(2024\)的数位和为\(2+0+2+4=8\)。一个正整数\(n\)被称作一个好数如果\(n\)能被它的数位和整除......