poj3185--The Water Bowls(高斯消元问题3)

The Water Bowls

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 4623   Accepted: 1812

Description

The cows have a line of 20 water bowls from which they drink. The bowls can be either right-side-up (properly oriented to serve refreshing cool water) or upside-down (a position which holds no water). They want all 20 water bowls
to be right-side-up and thus use their wide snouts to flip bowls.

Their snouts, though, are so wide that they flip not only one bowl but also the bowls on either side of that bowl (a total of three or -- in the case of either end bowl -- two bowls).

Given the initial state of the bowls (1=undrinkable, 0=drinkable -- it even looks like a bowl), what is the minimum number of bowl flips necessary to turn all the bowls right-side-up?

Input

Line 1: A single line with 20 space-separated integers

Output

Line 1: The minimum number of bowl flips necessary to flip all the bowls right-side-up (i.e., to 0). For the inputs given, it will always be possible to find some combination of flips that will manipulate the bowls to 20 0‘s.

Sample Input

0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0

Sample Output

3

Hint

Explanation of the sample:

Flip bowls 4, 9, and 11 to make them all drinkable:

0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 [initial state]

0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 [after flipping bowl 4]

0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 [after flipping bowl 9]

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [after flipping bowl 11]

Source

USACO 2006 January Bronze

题意很简单,每一次改变会改变三个数(自身和左右两侧),问最少多少步可以变为全为0

高斯消元,得出异或方程组,求出自由元,然后进行枚举,找出最小值。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define INF 0x3f3f3f3f
int Map[25][25] , a[25] , freex[25] , x[25] ;
void swap1(int p,int q)
{
    int i , temp ;
    temp = a[p] ;
    a[p] = a[q] ;
    a[q] = temp ;
    for(i = 0 ; i < 20 ; i++)
    {
        temp = Map[p][i] ;
        Map[p][i] = Map[q][i] ;
        Map[q][i] = temp ;
    }
    return ;
}
int solve()
{
    int i , j , k , t = 0 , num1 = 0 ;
    for(i = 0 ; i < 20 && t < 20 ; i++ , t++)
    {
        for(j = i ; j < 20 ; j++)
            if( Map[j][t] )
                break ;
        if( j == 20 )
        {
            freex[num1++] = t ;
            i-- ;
            continue ;
        }
        if( i != j )
            swap1(i,j) ;
        for(j = i+1 ; j < 20 ; j++)
        {
            if( Map[j][t] )
            {
                a[j] = a[j]^a[i] ;
                for(k = t ; k < 20 ; k++)
                    Map[j][k] = Map[j][k] ^ Map[i][k] ;
            }
        }
    }
    for( ; i < 20 ; i++)
        if( a[i] )
            return -1 ;
    if( num1 > 0 ) return num1 ;
    for(i = 19 ; i >= 0 ; i--)
    {
        x[i] = a[i] ;
        for(j = i+1 ; j < 20 ; j++)
            x[i] ^= ( Map[i][j]*x[j] ) ;
    }
    return num1 ;
}
int main()
{
    int i , j , k , min1 = INF , key , ans ;
    memset(Map,0,sizeof(Map)) ;
    for(i = 0 ; i < 20 ; i++)
        scanf("%d", &a[i]) ;
    for(i = 0 ; i < 20 ; i++)
    {
        Map[i][i] = 1 ;
        if( i-1 >= 0 ) Map[i][i-1] = 1 ;
        if( i+1 < 20 ) Map[i][i+1] = 1 ;
    }
    key = solve() ;
    if( key == 0 )
    {
        ans = 0 ;
        for(i = 0 ; i < 20 ; i++)
            ans += x[i] ;
        min1 = min(min1,ans) ;
    }
    else if( key > 0 )
    {
        int temp = 1 << key , t ;
        for(t = 0 ; t < temp ; t++)
        {
            ans = 0 ;
            memset(x,0,sizeof(x)) ;
            for(j = 0 ; j < key ; j++)
                if( t & (1<<j) )
                {
                    x[ freex[j] ] =1 ;
                    ans++ ;
                }
            for(i = 19 ; i >= 0 ; i--)
            {
                for(k = 0 ; k < 20 ; k++)
                    if( Map[i][k] )
                        break ;
                x[k] = a[i] ;
                for(j = k+1 ; j < 20 ; j++)
                    x[k] ^= ( Map[i][j]*x[j] ) ;
                ans += x[k] ;
            }
            min1 = min(min1,ans) ;
        }
    }
    printf("%d\n", min1) ;
    return 0;
}
时间: 2024-11-14 04:02:10

poj3185--The Water Bowls(高斯消元问题3)的相关文章

POJ 3185 The Water Bowls 高斯消元

高斯消元+位运算枚举自由变元 #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <set> #include <bitset> #include <queue> #include <stack> #include <string> #include <iostream> #i

poj 3185 The Water Bowls 高斯消元枚举变元

题目链接 给一行0 1 的数, 翻转一个就会使他以及它左右两边的都变, 求最少多少次可以变成全0. 模板题. #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include

poj 3185 The Water Bowls(高斯消元)

The Water Bowls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4352   Accepted: 1721 Description The cows have a line of 20 water bowls from which they drink. The bowls can be either right-side-up (properly oriented to serve refreshing

[ACM] POJ 2947 Widget Factory (高斯消元)

Widget Factory Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 4436   Accepted: 1502 Description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to

高斯消元【转】

转载注明出处 高消一直是ACM中高层次经常用到的算法,虽然线性代数已经学过,但高消求解的问题模型及高消模板的应用变化是高消的最复杂之处. 先介绍一下高消的基本原理:引入互联网czyuan的帖子: 高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵. 高斯消元法的原理是: 若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. 所以我们可以用初等行变换把增广矩阵转换为行阶梯阵,然后回代求出方程的解. 以上是线性代数课的回顾,

2016 CCPC 网络赛 B 高斯消元 C 树形dp(待补) G 状压dp+容斥(待补) H 计算几何

2016 CCPC 网络赛 A - A water problem 水题,但读题有个坑,输入数字长度很大.. B - Zhu and 772002 题意:给出n个数(给出的每个数的质因子最大不超过2000),选出多个数相乘得b.问有多少种选法让b 为完全平方数. tags:高斯消元,求异或方程组解的个数.   好题 每个数先素数分解开.  对于2000以内的每个素数p[i],这n个数有奇数个p[i]则系数为1,偶数个则系数为0,最后n个数的p[i]系数异或和都要为0才会使得最后的积为完全平方数.

poj_1222_高斯消元

第一次学习使用高斯消元,将灯板化为线性方程组,进行求解. /*######################################################################### # File Name: poj_1222.cpp # Author: CaoLei # Created Time: 2015/7/20 15:48:04 ###################################################################

HDU 4870 Rating(高斯消元)

HDU 4870 Rating 题目链接 题意:一个人注册两个账号,初始rating都是0,他每次拿低分的那个号去打比赛,赢了加50分,输了扣100分,胜率为p,他会打到直到一个号有1000分为止,问比赛场次的期望 思路:f(i, j)表示i >= j,第一个号i分,第二个号j分时候,达到目标的期望,那么可以列出转移为f(i, j) = p f(i', j') + (1 - p) f(i'' + j'') + 1 f(i', j')对应的是赢了加分的状态,f(i'', j'')对应输的扣分的状态

【BZOJ 4171】 4171: Rhl的游戏 (高斯消元)

4171: Rhl的游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 74  Solved: 33[Submit][Status][Discuss] Description RHL最近迷上一个小游戏:Flip it.游戏的规则很简单,在一个N*M的格子上,有一些格子是黑色,有一些是白色 .每选择一个格子按一次,格子以及周围边相邻的格子都会翻转颜色(边相邻指至少与该格子有一条公共边的格子 ),黑变白,白变黑.RHL希望把所有格子都变成白色的.不幸