POJ 3185 The Water Bowls (高斯消元 求最小步数)

题目链接

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

分析:

和上一题差不多,但是比上一题还简单,不多说了,但是在做题的时候犯了一个非常二的错误。。看图吧。

先输入了a[0]又,初始了a[]【】数组

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <algorithm>
  7 #define LL __int64
  8 const int maxn = 400+10;
  9 const int INF = 1<<28;
 10 using namespace std;
 11 int equ, var, fn;
 12 int a[maxn][maxn], x[maxn];
 13 int free_x[maxn];
 14 int gcd(int a, int b)
 15 {
 16     return b==0?a:gcd(b, a%b);
 17 }
 18 int lcm(int a, int b)
 19 {
 20     return a*b/gcd(a, b);
 21 }
 22 int Gauss()
 23 {
 24     int x_mo;
 25     x_mo = 2;
 26     int i, j, k, max_r, col;
 27     int ta, tb, LCM, fx_num = 0;
 28     col = 0;
 29 
 30     for(k = 0; k<equ && col<var; k++, col++)
 31     {
 32         max_r = k;
 33         for(i = k+1; i < equ; i++)
 34             if(abs(a[i][col])>abs(a[max_r][col]))
 35                 max_r = i;
 36 
 37         if(max_r != k)
 38             for(j = k; j < var+1; j++)
 39                 swap(a[k][j], a[max_r][j]);
 40 
 41         if(a[k][col]==0)
 42         {
 43             free_x[fx_num++] = col; //求自由变元所在的列
 44             k--;
 45             continue;
 46         }
 47         for(i = k+1; i < equ; i++)
 48         {
 49             if(a[i][col] != 0)
 50             {
 51                 LCM = lcm(abs(a[i][col]), abs(a[k][col]));
 52                 ta = LCM/abs(a[i][col]);
 53                 tb= LCM/abs(a[k][col]);
 54                 if(a[i][col]*a[k][col] < 0) tb = -tb;
 55 
 56                 for(j = col; j < var+1; j++)
 57                     a[i][j] = ((a[i][j]*ta - a[k][j]*tb)%x_mo+x_mo)%x_mo;
 58             }
 59         }
 60     }
 61     for(i = k; i < equ; i++)
 62         if(a[i][col] != 0)
 63             return INF;
 64 
 65     int stat=1<<(var-k);
 66     int res=INF;
 67     for(i=0; i<stat; i++)
 68     {
 69         int cnt=0;
 70         int index=i;
 71         for(j=0; j<var-k; j++)
 72         {
 73             x[free_x[j]]=(index&1);
 74             if(x[free_x[j]]) cnt++;
 75             index>>=1;
 76         }
 77         for(j=k-1; j>=0; j--)
 78         {
 79             int tmp=a[j][var];
 80             for(int l=j+1; l<var; l++)
 81                 if(a[j][l]) tmp^=x[l];
 82             x[j]=tmp;
 83             if(x[j])cnt++;
 84         }
 85         if(cnt<res)res=cnt;
 86     }
 87     return res;
 88 }
 89 
 90 void init()
 91 {
 92     int i;
 93     memset(a, 0, sizeof(a));
 94     memset(x, 0, sizeof(x));
 95     for(i = 0; i < 20; i++)
 96     {
 97         a[i][i] = 1;
 98         if(i+1<20)
 99         a[i+1][i] = 1;
100         if(i-1>=0)
101         a[i-1][i] = 1;
102     }
103 }
104 int main()
105 {
106     int i;
107         equ = 20;
108         var = 20;
109         init();
110         for(i = 0; i < 20; i++)
111         scanf("%d", &a[i][20]);
112         fn = Gauss();
113         printf("%d\n", fn);
114     return 0;
115 }

 

posted @ 2014-08-19 11:00  水门  阅读(159)  评论(0编辑  收藏  举报