【POJ】3185 The Water Bowls

题意:有20个数字,0或1。如果改变一个数的状态,它左右两边的两个数的状态也会变反。问从目标状态到全0,至少需要多少次操作。

显然,问题可以从目标状态到全0 转化为 全0到目标状态。

于是可以列出方程组,每行一个数的状态。

为了知道操作次数,那么就要知道未知数为1有多少个,所以就要解方程组,解方程组就不得不枚举自由元了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define MAXN 20
 5 #define MAXM 25
 6 #define oo 0x7FFFFFFF
 7 using namespace std;
 8 int g[MAXM][MAXM], tmp[MAXM], x[MAXM];
 9 int ans;
10 bool Read() {
11     int i;
12     for (i = 0; i < MAXN; i++) {
13         if (scanf("%d", &g[i][MAXN]) == EOF)
14             return false;
15     }
16     return true;
17 }
18 int Cal() {
19     int i, j, k, cnt;
20     k = cnt = 0;
21     for (i = MAXN - 1; i >= 0; i--) {
22         if (g[i][i]) {
23             x[i] = g[i][MAXN];
24             for (j = i + 1; j < MAXN; j++)
25                 x[i] ^= x[j] && g[i][j];
26         } else
27             x[i] = tmp[k++];
28         if (x[i])
29             cnt++;
30     }
31     return cnt;
32 }
33 void DFS(int now, int cnt) {
34     if (cnt == 0)
35         ans = min(ans, Cal());
36     else {
37         tmp[now] = 0;
38         DFS(now + 1, cnt - 1);
39         tmp[now] = 1;
40         DFS(now + 1, cnt - 1);
41     }
42 }
43 void Gauss() {
44     int r, c, i, j;
45     for (c = r = 0; c < MAXN; c++, r++) {
46         for (i = r; i < MAXN; i++) {
47             if (g[i][c])
48                 break;
49         }
50         if (i >= MAXN)
51             r--;
52         else {
53             if (i != r) {
54                 for (j = 0; j <= MAXN; j++)
55                     swap(g[i][j], g[r][j]);
56             }
57             for (i = r + 1; i < MAXN; i++) {
58                 if (g[i][c]) {
59                     for (j = c; j <= MAXN; j++)
60                         g[i][j] ^= g[r][j];
61                 }
62             }
63         }
64     }
65     DFS(0, MAXN - r);
66 }
67 int main() {
68     int i;
69     while (Read()) {
70         for (i = 0; i < MAXN; i++) {
71             g[max(i - 1, 0)][i] = 1;
72             g[i][i] = 1;
73             g[min(MAXN - 1, i + 1)][i] = 1;
74         }
75         ans = oo;
76         Gauss();
77         printf("%d\n", ans);
78     }
79     return 0;
80 }

转载于:https://www.cnblogs.com/DrunBee/archive/2012/09/03/2668280.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值