这道题抄了答案:

思路:旋转,其实只用旋转四次,因为在换行的过程中旋转其实是没有意义的,因为行列只不过转了个角度。然后主要的是行列的交换,这里我很头疼,写了个盲目搜索,当然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. jmeter 与 java http

    jmeter 如果对java代码进行测试 1.eclips中创建一个项目,且写一个待测试的简单java代码 2.将jmeter路径下 x:\xx\lxx\Dowxxxxxx\apache-jmeter ...

  2. Mysql备份系列(1)--备份方案总结性梳理

    mysql数据库备份有多么重要已不需过多赘述了,废话不多说!以下总结了mysql数据库的几种备份方案: 一.binlog二进制日志通常作为备份的重要资源,所以再说备份方案之前先总结一下binlog日志 ...

  3. Structs2配置文件相关说明

    1,structs.xml文件解析 <package name="front" namespace="/front" extends="stru ...

  4. 错题724-java

    1.代码片段: byte b1=1,b2=2,b3,b6; final byte b4=4,b5=6; b6=b4+b5; b3=(b1+b2); System.out.println(b3+b6); ...

  5. 教你如何调用百度编辑器ueditor的上传图片、上传文件等模块

    出于兴趣爱好,前段时间自己尝试写了一个叫simple的cms,里面使用了百度ueditor编辑器,发现它的多图片上传模块很不错,用起来很方便,又可以选择已经上传好的图片.正好我又是个懒人,发现有现成的 ...

  6. Winfrom动态创建控件

    FlowLayoutPanel flowLayoutPanel1 = new FlowLayoutPanel();for (int i = 0; i < 9; i++){    Button b ...

  7. noi题库(noi.openjudge.cn) 1.9编程基础之顺序查找T01——T05

    T01 查找特定元素的值 描述 在一个序列(下标从1开始)中查找一个给定的值,输出第一次出现的位置. 输入 第一行包含一个正整数n,表示序列中元素个数.1 <= n <= 10000.第二 ...

  8. Pechkin:html -> pdf 利器

    Pechkin 是GitHub上的一个开源项目,可方便将html转化成pdf文档,使用也很方便,下面是winform项目中的示例代码: using System; using System.Diagn ...

  9. TinyFrame升级之九:实现复杂的查询

    本章我们主要讲解如何实现一个复杂的查询.由于目前TinyFrame框架已经投入到了实际的项目生产中,所以我很乐意将项目中遇到的任何问题做以记录并备忘. 这章中,我们提到的查询界面如下所示: 其中,涉及 ...

  10. sleep和wait的区别有:

    sleep和wait的区别有: 1,这两个方法来自不同的类分别是Thread和Object 2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得敏感词线程可以使用同步控制块或者方法. 3 ...