【CQOI2013】新数独

链接


考虑搜索。

将每行,每列,每块的状态压缩,然后爆搜就可以了。

写起来比较质朴,老老实实敲完就可以了。

输入的时候处理信息需要一些技巧(参见代码中的now_l,now_p)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 
 8 int cnet[90][90],vis[90][90];
 9 int mp[10][10];
10 int lr[10],ud[10],bl[10];
11 int bel[90];
12 int flag=0;
13 int dr[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
14 
15 inline int id(int x,int y){
16     return (x-1)*9+y;
17 }
18 inline int lb(int x){
19     return x&(-x);
20 }
21 inline bool wall(int x,int y){
22     if(x<1||y<1||x>9||y>9)return false;
23     return true;
24 }
25 inline bool check(int dx,int dy,int x,int y){
26     if(wall(dx,dy)&&mp[dx][dy]&&cnet[id(dx,dy)][id(x,y)]!=-1)return true;
27     return false;
28 }
29 inline void dfs(int now){
30     int idx=(now-1)/9+1,idy=((now-1)%9)+1;
31     if(now==82){
32         flag=1;return;
33     }
34     int rest=lr[idx]&ud[idy]&bl[bel[now]];
35     while(rest){
36         int pos=lb(rest);rest-=pos;
37         pos=log2(pos)+1;
38         int unable=0;
39         for(int i=0;i<4;i++){
40             int dx=idx+dr[i][0],dy=idy+dr[i][1];
41             if(check(dx,dy,idx,idy)&&(pos>mp[dx][dy])!=cnet[now][id(dx,dy)]){
42                 unable=1;break;
43             }
44         }
45         if(unable)continue;
46         mp[idx][idy]=pos;
47         lr[idx]-=(1<<(pos-1));ud[idy]-=(1<<(pos-1));bl[bel[now]]-=(1<<(pos-1));
48         dfs(now+1);
49         if(flag)return;
50         mp[idx][idy]=0;
51         lr[idx]|=(1<<(pos-1));ud[idy]|=(1<<(pos-1));bl[bel[now]]|=(1<<(pos-1));
52     }
53 }
54 char ch[10];
55 int now_l=1,now_p=0;
56 int main(){
57     memset(cnet,-1,sizeof(cnet));
58     for(int i=1;i<=15;i++){
59         if(i%5==2||i%5==4){
60             ++now_l;
61             for(int j=1;j<=9;j++){
62                 int x=id(now_l,j),y=x-9;
63                 scanf("%s",ch+1);
64                 cnet[x][y]=(ch[1]=='^'?1:0);
65                 cnet[y][x]=cnet[x][y]^1;
66             }
67         }
68         else{
69             now_p=0;
70             for(int j=1;j<=6;j++){
71                 ++now_p;
72                 if(now_p%3==0)++now_p;
73                 int x=id(now_l,now_p);
74                 scanf("%s",ch+1);
75                 cnet[x][x+1]=(ch[1]=='>'?1:0);
76                 cnet[x+1][x]=cnet[x][x+1]^1;
77             }
78         }
79         if(i%5==0)++now_l;
80     }
81     for(int i=1;i<=9;i++){
82         for(int j=1;j<=9;j++){
83             int x=id(i,j);
84             bel[x]=(i-1)/3*3+(j-1)/3+1;
85         }
86     }
87     for(int i=1;i<=9;i++){
88         lr[i]=ud[i]=bl[i]=(1<<9)-1;
89     }
90     dfs(1);
91     for(int i=1;i<=9;i++){
92         for(int j=1;j<=9;j++){
93             printf("%d ",mp[i][j]);
94         }
95         puts("");
96     }
97 }

一个晚自习就改了一个题。

觉得挺值了吧,第一次写2^n以下的搜索。

“好呀,我A了,写了九十多行”(zzm写了200+)

zzm:“你看看你用了多少时间”

......

超生气的。

转载于:https://www.cnblogs.com/chiyo/p/11178560.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值