P1092 [NOIP2004 提高组] 虫食算

原题链接

考察:dfs+剪枝

思路:

        从最后一列开始dfs,用bool 数组记录哪些数字被使用了即可.接下来思考如何剪枝:

  1. 搜索顺序剪枝: 从大到小枚举,大数字在低位可能性较大.
  2. 冗余处理:这里是排列型枚举.
  3. 可行性剪枝:比较关键,需要两个剪枝:高位无进位.  从第1列~第n列检查是否符合实际.
  4. 最优性剪枝:无
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int N = 30;
 6 int n,a[N],b[N];
 7 char s[4][N];
 8 bool st[N];
 9 int Getid(int i,int j)
10 {
11     return s[i][j]-'A';
12 }
13 bool check()
14 {
15     int s1 = Getid(1,1),s2 = Getid(2,1),s3;
16     if(a[s1]!=-1&&a[s2]!=-1)
17     {
18         int K = a[s1]+a[s2];
19         if(K>=n) return 1;
20     }
21     for(int i=2;i<=n;i++)
22     {
23         s1 = Getid(1,i),s2 = Getid(2,i),s3 = Getid(3,i);
24         if(a[s1]==-1||a[s2]==-1) continue;
25         int res = a[s1]+a[s2];
26         if(a[s3]!=-1&&(res+1)%n!=a[s3]&&res%n!=a[s3]) return 1;
27         if(a[s3]==-1&&st[(res+1)%n]&&st[res%n]) return 1; 
28     }
29     return 0;
30 }
31 bool dfs(int k,int p)
32 {
33     if(!k) return 1;
34     if(check()) return 0;
35     int pos = Getid(p,k);
36     if(a[pos]!=-1&&p<3) return dfs(k,p+1);
37     if(p==3)
38     {
39         int s1 = s[1][k]-'A',s2 = s[2][k]-'A';
40         int now = (a[s1]+a[s2]+b[k])%n;
41         int tmp = (a[s1]+a[s2]+b[k])/n;
42         if(a[pos]!=-1)
43         {
44             if(now!=a[pos]) return 0;
45             else
46             {
47                 b[k-1] += tmp;
48                 if(dfs(k-1,1)) return 1;
49                 b[k-1] -= tmp;
50                 return 0;
51             }
52         }else{
53             if(st[now]) return 0;
54             st[now] = 1;
55             a[pos] = now; 
56             b[k-1] += tmp;
57             if(dfs(k-1,1)) return 1;
58             st[now] = 0;
59             a[pos] = -1;
60             b[k-1] -= tmp;
61             return 0;
62         }
63     }
64     for(int i=n-1;i>=0;i--)
65     {
66         if(st[i]) continue;
67         a[pos] = i;
68         st[i] = 1;
69         if(dfs(k,p+1)) return 1;
70         st[i] = 0;
71         a[pos] = -1;
72     }
73     return 0;
74 }
75 int main()
76 {
77     scanf("%d",&n);
78     memset(a,-1,sizeof a);
79     for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
80     if(dfs(n,1)) 
81          for(int i=0;i<n;i++) printf("%d ",a[i]);
82     return 0;
83 }

 

posted @ 2021-03-10 12:21  acmloser  阅读(170)  评论(0编辑  收藏  举报