poj 3185 贪心翻硬币 高斯消元

来源:互联网 发布:淘宝预售发货规则 编辑:程序博客网 时间:2024/05/16 08:54

题意:

有20个硬币,每次选择翻转,翻转i的时候,i-1 , i+1 都会被翻成相反面。

现在给20个硬币的状态,求最少翻多少次能把这些硬币都翻成0。


解析:

翻两次等于没翻,从最左或者最右开始去翻就行了。

这题数据好水而且很坑,没有检查越界访问都能过。。。

好像hdu4200比较有学习意义。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = 4 * atan(1.0);const double ee = exp(1.0);const int maxn = 10000 + 10;int a[30];int b[30];int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (~scanf("%d", &a[0]))    {        b[0] = a[0];        for (int i = 1; i < 20; i++)        {            scanf("%d", &a[i]);            b[i] = a[i];        }        int ansA = 0;        for(int i = 1; i <= 20; i++)        {            if(a[i - 1])            {                a[i] = !a[i];                a[i - 1] = !a[i - 1];                a[i + 1] = !a[i + 1];                ansA++;            }        }        int ansB = 0;        for(int i = 19; i >= 0; i--)        {            if(b[i + 1])            {                b[i] = !b[i];                b[i - 1] = !b[i - 1];                b[i + 1] = !b[i + 1];                ansB++;            }        }        printf("%d\n", min(ansA, ansB));    }    return 0;}


高斯消元枚举自由元代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = 4 * atan(1.0);const double ee = exp(1.0);const int maxn = 1000 + 10;int a[maxn][maxn];  //增广矩阵int x[maxn];        //解集int freeX[maxn];   //记录自由变元在哪行int gcd(int a, int b){    return b ? gcd(b, a % b) : a;}int lcm(int a, int b){    return a / gcd(a, b) * b;}//高斯消元解方程组//返回值-2表示有浮点数解,无整数解//返回值-1表示无解,0表示有唯一解,大于0表示有无穷解,返回自由变元个数//有equ个方程,var个变元//增广矩阵行数[0, equ - 1]//增广矩阵列数[0, var]int gauss(int equ, int var){    int num = 0;    for (int i = 0; i <= var; i++)    {        x[i] = 0;        freeX[i] = 0;    }    //转换为阶梯矩阵    //col表示当前正在处理的这一列    int col = 0;    int row = 0;    //maxR表示当前这个列中元素绝对值最大的行    int maxRow;    for (; row < equ && col < var; row++, col++)    {        //枚举当前正在处理的行        //找到该col列元素绝对值最大的那行与第k行交换        maxRow = row;        for (int i = row + 1; i < equ; i++)        {            if (abs(a[maxRow][col]) < abs(a[i][col]))            {                maxRow = i;            }        }        if (maxRow != row)        {            //与第row行交换            for (int j = row; j < var + 1; j++)            {                swap(a[row][j], a[maxRow][j]);            }        }        if (a[row][col] == 0)        {            //说明该col列第row行以下全是0,处理当前行的下一列            row--;            freeX[num++] = col;            continue;        }        for (int i = row + 1; i < equ; i++)        {            //枚举要删的行            if (a[i][col] != 0)            {                for (int j = col; j < var + 1; j++)                {                    ///                    a[i][j] ^= a[row][j];                }            }        }    }    for (int i = row; i < equ; i++)    {        if (a[i][col] != 0)        {            return -1;        }    }    int state = 1 << (var - row);    int res = inf;    for (int i = 0; i < state; i++)    {        int cnt =0 ;        int index = i;        for (int j = 0; j < var - row; j++)        {            x[freeX[j]] = (index & 1);            if (x[freeX[j]])                cnt++;            index >>= 1;        }        for (int j = row - 1; j >= 0; j--)        {            int tmp = a[j][var];            for (int l = j + 1; l < var; l++)            {                if (a[j][l])                    tmp ^= x[l];            }            x[j] = tmp;            if (x[j])                cnt++;        }        if (cnt < res)            res = cnt;    }    return res;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (~scanf("%d", &a[0][20]))    {        for (int i = 0; i < 20; i++)        {            for (int j = 0; j < 20; j++)            {                a[i][j] = 0;            }        }        for (int i = 0; i < 20; i++)        {            a[i][i] = 1;            if (i > 0)                a[i][i - 1] = 1;            if (i < 19)                a[i][i + 1] = 1;        }        for (int i = 1; i < 20; i++)        {            scanf("%d", &a[i][20]);        }        int ans = gauss(20, 20);        printf("%d\n", ans);    }    return 0;}


0 0