这道题抄了答案:

思路:旋转,其实只用旋转四次,因为在换行的过程中旋转其实是没有意义的,因为行列只不过转了个角度。然后主要的是行列的交换,这里我很头疼,写了个盲目搜索,当然wa掉了

问了问某位同志,是这样做的,很巧妙:其实这是一个全排列,一个三个数的全排列套了三个数的全排列,然后该怎么做呢?这里运用了一个巧妙的方法:range

range很巧妙,分两种情况:当我选完了三列时,这时我需要新的一列,那么我返回(0,8),意思是下一个列可以从(0,8)之间没用过的任选。第二呢,是我正在选三列中的一列,这时

我看看上一列我选的什么,这次我选的只能是(上一列设为x)[x/3*3,x/3*3+2]举个例子:(0,1,2) (3,4,5)(6,7,8)其实就是这三个块,他们每三个数必须绑在一起

然后我搜完了列之后搜行(搜行的时候我犯了个错误,对应残缺的数独下标没想清楚,debug了很长时间,下次应该想清楚)然后就是重复同样的过程,只不过要加上置换,

置换需要用一个额外的数组记录是那一列的时候替换的,因为会导致还原的时候不知道哪些要还原,然后就好了。

#include<iostream>
#include<cstring>
#include<cstdio> using namespace std; typedef pair<int,int> pii; string s;
int used_col[],used_row[],place[];
int pos_row[],pos_col[],place_flag[];
int b[][],c[][]; void init()
{
memset(place_flag,-,sizeof(place_flag));
memset(place,-,sizeof(place));
memset(pos_row,-,sizeof(pos_row));
memset(pos_col,-,sizeof(pos_col));
memset(used_row,,sizeof(used_row));
memset(used_col,,sizeof(used_col));
} pii get_range(int pos,int f)
{
if(pos%==) return pii(,);
int head=;
if(!f) head=pos_row[pos-]/*;
else head=pos_col[pos-]/*;
return pii(head,head+);
} void rotate()
{
int a[][];memset(a,,sizeof(a));
for(int i=;i<;i++)
for(int j=;j<;j++) a[-j-][i]=b[i][j];
for(int i=;i<;i++)
for(int j=;j<;j++) b[i][j]=a[i][j];
} bool go_col(int d)
{
if(d==) return true;
pii range=get_range(d,);
for(int i=range.first;i<=range.second;i++) if(!used_col[i])
{
used_col[i]=;
pos_col[d]=i;
bool flag=false;
for(int j=;j<;j++)
{
int x=b[pos_row[j]][pos_col[d]],y=c[j][d];
if(y==) continue;
if(place[x]!=-&&place[x]!=y) {flag=true;break;}
if(place[x]==-)
{
place[x]=y;
place_flag[x]=d;
}
}
if(!flag) if(go_col(d+)) return true;
for(int j=;j<;j++)
{
int x=b[pos_row[j]][pos_col[d]];
if(place_flag[x]==d) {place_flag[x]=-;place[x]=-;}
}
used_col[i]=;
pos_col[d]=-;
}
return false;
} bool go_row(int d)//行
{
if(d==) return go_col();
pii range=get_range(d,);
for(int i=range.first;i<=range.second;i++)
{
if(!used_row[i])
{
used_row[i]=;
pos_row[d]=i;
if(go_row(d+)) return true;
used_row[i]=;
pos_row[d]=-;
}
}
return false;
} bool work()
{
for(int i=;i<;i++)
{
init();
rotate();
if(go_row()) return true;
}
return false;
} int main()
{
int T;scanf("%d",&T);
while(T--)
{
for(int i=;i<;i++)
{
cin>>s;
for(int j=;j<;j++)
{
b[i][j]=s[j]-'';
}
}
for(int i=;i<;i++)
{
cin>>s;
for(int j=;j<;j++)
{
c[i][j]=s[j]-'';
}
}
if(work()) printf("Yes\n"); else printf("No\n");
}
return ;
}

100722A的更多相关文章

随机推荐

  1. python中if __name__ == "__main__":用法解析

    __name__: __name__作为模块的内置属性,简单点说呢,就是.py文件的调用方式. __main__: 如果__name__等于"__main__"就表示是直接执行. ...

  2. Oracle取TOP N条记录(转载)

    在SQL Server里面有top关键字可以很方便的取出前N条记录,但是Oracle里面却没有top的使用,类似实现取出前N条记录的简单方法如下: 方法1:利用ROW_NUMBER函数 取出前5条记录 ...

  3. python中的字符串操作

    #!/usr/bin/python # -*- coding: UTF-8 -*- ''' str.capitalize() ''' str = 'this is a string example' ...

  4. 04Spring_bean 后处理器(后处理Bean),BeanPostProcessor ,bean创建时序,动态代理

    这篇文章很重要,讲解的是动态代理,以及bean创建前后的所发生的事情.介绍一个接口:在Spring构造Bean对象过程中,有一个环节对Bean对象进行 后处理操作 (钩子函数) ----- Sprin ...

  5. 如何迁移Alwayson AG

    Windows cluster要求同一个cluster中的所有windows版本都是相同的,这样就出现一个问题,当我们要将对windows进行升级时,(例如从windows 2008 R2升级到win ...

  6. Dynamics CRM 2016 的新特性

    新版本CRM (2016 with update 0.1) 发布已有几个月了,总结一下新特性,从几个方面来看: 1. 针对整合功能的新特性 (1) 增加了CRM App for Outlook. 这个 ...

  7. Castle.ActiveRecord 多对多关系 引发的错误处理

    在Castle.ActiveRecord 实体类中,如果两个对象有 “多对多” 关系,一般的做法是将其分解为 两个“一对多”关系,但有时引发了 “您要删除 或 引用 的对象#2在数据库中不存在”的异常 ...

  8. Spring 4.0.2 学习笔记(2) - 自动注入及properties文件的使用

    接上一篇继续, 学习了基本的注入使用后,可能有人会跟我一样觉得有点不爽,Programmer的每个Field,至少要有一个setter,这样spring配置文件中才能用<property> ...

  9. 智普教育Python培训之Python开发视频教程网络爬虫实战项目

    网络爬虫项目实训:看我如何下载韩寒博客文章Python视频 01.mp4 网络爬虫项目实训:看我如何下载韩寒博客文章Python视频 02.mp4 网络爬虫项目实训:看我如何下载韩寒博客文章Pytho ...

  10. 如何配置多个ssh key

    上一篇简单学习了下怎样利用git bash上传文件到指定的github项目中,我们来回顾下.首先在本地安装好git,设置好用户名和邮箱(提交时的显示),接着我们生成SSH key把它添加到该项目own ...