【FOJ】2076 SUDOKU

  1 #include<cstdio>

  2 #include<cstring>

  3 #include<set>

  4 #define MAXN 9

  5 #define MAXM 500000

  6 #define INF 0x7FFFFFFF

  7 using namespace std;

  8 char sd[MAXN][MAXN];

  9 int L[MAXM], R[MAXM], U[MAXM], D[MAXM];

 10 int H[MAXM], S[MAXM], C[MAXM], pos[MAXN << 3][MAXN << 3];

 11 int size, cnt;

 12 void Init(int m)

 13 {

 14     int i;

 15     for (i = 0; i <= m; i++)

 16     {

 17         R[i] = i + 1;

 18         L[i + 1] = i;

 19         U[i] = D[i] = i;

 20         S[i] = 0;

 21     }

 22     R[m] = 0;

 23     size = m + 1;

 24 }

 25 void Remove(int c)

 26 {

 27     int i, j;

 28     L[R[c]] = L[c];

 29     R[L[c]] = R[c];

 30     for (i = D[c]; i != c; i = D[i])

 31     {

 32         for (j = R[i]; j != i; j = R[j])

 33         {

 34             U[D[j]] = U[j];

 35             D[U[j]] = D[j];

 36             S[C[j]]--;

 37         }

 38     }

 39 }

 40 void Resume(int c)

 41 {

 42     int i, j;

 43     L[R[c]] = R[L[c]] = c;

 44     for (i = D[c]; i != c; i = D[i])

 45     {

 46         for (j = R[i]; j != i; j = R[j])

 47         {

 48             U[D[j]] = D[U[j]] = j;

 49             S[C[j]]++;

 50         }

 51     }

 52 }

 53 inline void Link(int r, int c)

 54 {

 55     U[size] = c;

 56     D[size] = D[c];

 57     U[D[c]] = size;

 58     D[c] = size;

 59     if (H[r] < 0)

 60         H[r] = L[size] = R[size] = size;

 61     else

 62     {

 63         L[size] = H[r];

 64         R[size] = R[H[r]];

 65         L[R[H[r]]] = size;

 66         R[H[r]] = size;

 67     }

 68     S[c]++;

 69     C[size++] = c;

 70 }

 71 void Dance()

 72 {

 73     if (R[0] == 0)

 74         cnt++;

 75     else

 76     {

 77         int i, j, temp, c;

 78         for (temp = INF,i = R[0]; i; i = R[i])

 79         {

 80             if (temp > S[i])

 81             {

 82                 temp = S[i];

 83                 c = i;

 84             }

 85         }

 86         Remove(c);

 87         for (i = D[c]; i != c; i = D[i])

 88         {

 89             for (j = R[i]; j != i; j = R[j])

 90                 Remove(C[j]);

 91             Dance();

 92             for (j = L[i]; j != i; j = L[j])

 93                 Resume(C[j]);

 94         }

 95         Resume(c);

 96     }

 97 }

 98 void Build()

 99 {

100     set<int> myset;

101     int i, j, k, r, t;

102     for (i = r = 0; i < MAXN; i++)

103     {

104         for (j = 0; j < MAXN; j++)

105         {

106             if (sd[i][j] == '0')

107             {

108                 for (k = 1; k <= MAXN; k++)

109                 {

110                     H[++r] = -1;

111                     Link(r, i * 9 + k);

112                     Link(r, 81 + j * 9 + k);

113                     Link(r, 162 + (i / 3 * 3 + j / 3) * 9 + k);

114                     Link(r, 243 + i * 9 + j + 1);

115                 }

116             }

117             else if (sd[i][j] >= '1' && sd[i][j] <= '9')

118             {

119                 k = sd[i][j] - '0';

120                 H[++r] = -1;

121                 Link(r, i * 9 + k);

122                 Link(r, 81 + j * 9 + k);

123                 Link(r, 162 + (i / 3 * 3 + j / 3) * 9 + k);

124                 Link(r, 243 + i * 9 + j + 1);

125             }

126         }

127     }

128     for (i = 0; i < 26; i++)

129     {

130         for (j = 0; j < MAXN; j++)

131         {

132             pos[i][j] = ++r;

133             H[r] = -1;

134         }

135     }

136     for (i = 0; i < MAXN; i++)

137     {

138         for (j = 0; j < MAXN; j++)

139         {

140             if (sd[i][j] >= 'a' && sd[i][j] <= 'z')

141             {

142                 t = sd[i][j] - 'a';

143                 for (k = 1; k <= MAXN; k++)

144                 {

145                     Link(pos[t][k - 1], i * 9 + k);

146                     Link(pos[t][k - 1], 81 + j * 9 + k);

147                     Link(pos[t][k - 1], 162 + (i / 3 * 3 + j / 3) * 9 + k);

148                     Link(pos[t][k - 1], 243 + i * 9 + j + 1);

149                     if (!myset.count(t * 26 + k - 1))

150                     {

151                         Link(pos[t][k - 1], 324 + k);

152                         myset.insert(t * 26 + k - 1);

153                     }

154                 }

155             }

156         }

157     }

158     for (i = 1; i <= MAXN; i++)

159     {

160         H[++r] = -1;

161         Link(r, 324 + i);

162     }

163 }

164 inline int Get(char ch)

165 {

166     if (ch >= '0' && ch <= '9')

167         return ch - '0';

168     return ch - 'a' + 10;

169 }

170 bool OK()

171 {

172     int i, j, k;

173     bool x[MAXN << 3], letter[MAXN << 3], y[MAXN][MAXN << 3];

174     memset(letter, false, sizeof(letter));

175     memset(y, false, sizeof(y));

176     for (i = 0; i < MAXN; i++)

177     {

178         memset(x, false, sizeof(x));

179         for (j = 0; j < MAXN; j++)

180         {

181             k = Get(sd[i][j]);

182             if (k && y[i / 3 * 3 + j / 3][k])

183                 return false;

184             y[i / 3 * 3 + j / 3][k] = true;

185             if (k > 9)

186                 letter[k] = true;

187             if (k && x[k])

188                 return false;

189             x[k] = true;

190         }

191     }

192     for (i = k = 0; i < MAXN << 3; i++)

193     {

194         if (letter[i])

195             k++;

196     }

197     if (k > 9)

198         return false;

199     for (j = 0; j < MAXN; j++)

200     {

201         memset(x, false, sizeof(x));

202         for (i = 0; i < MAXN; i++)

203         {

204             k = Get(sd[i][j]);

205             if (k && x[k])

206                 return false;

207             x[k] = true;

208         }

209     }

210     return true;

211 }

212 int main()

213 {

214     int c, i, j;

215     scanf("%d", &c);

216     while (c--)

217     {

218         Init(333);

219         for (i = cnt = 0; i < MAXN; i++)

220         {

221             for (j = 0; j < MAXN; j++)

222                 scanf(" %c", &sd[i][j]);

223         }

224         if (OK())

225         {

226             Build();

227             Dance();

228         }

229         printf("%d\n", cnt);

230     }

231     return 0;

232 }

你可能感兴趣的:(sudo)