poj 3185 The Water Bowls

The Water Bowls

 POJ - 3185 

一个由20个数字(0或1)组成的数列,问最少操作多少次能将其变成一个全0数列,每次操作可以选择一个数字,将其左边右边和本身翻转

#include<iostream>
#include<cstdio>
using namespace std;
int a[22],b[22],ans1,ans2;
int main(){
    for(int i=1;i<=20;i++)scanf("%d",&a[i]),b[i]=a[i];
    for(int i=2;i<=20;i++){
        if(a[i-1]==1){
            a[i-1]^=1;
            a[i]^=1;
            a[i+1]^=1;
            ans1++;
        }
    }
    for(int i=19;i>=1;i--){
        if(b[i+1]==1){
            b[i+1]^=1;
            b[i]^=1;
            b[i-1]^=1;
            ans2++;
        }
    }
    printf("%d",min(ans1,ans2));
    return 0;
}
100分 贪心(从左到右或从右到左)
#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 0x3fffffff
#define maxn 20
using namespace std;
int a[22][22],x[22],free_n;
int gcd(int a,int b){
    if(a<0)return gcd(-a,b);
    if(b<0)return gcd(a,-b);
    return b==0?a:gcd(b,a%b);
}
int guass(){
    int k,col=0;
    for(k=0;k<20&&col<20;k++,col++){
        int mx=k;
        for(int i=k+1;i<20;i++)
            if(a[i][col]>a[mx][col])mx=i;
        for(int i=k;i<21;i++)swap(a[k][i],a[mx][i]);
        if(!a[k][col]){k--;continue;}//不太明白为什么要k-- 
        for(int i=k+1;i<20;i++){//这个循环都不明白 
            if(a[i][col]!=0){
                int lcm=a[k][col]/gcd(a[k][col],a[i][col])*a[i][col];
                int ta=lcm/a[i][col],tb=lcm/a[k][col];
                if(a[i][col]*a[k][col]<0)tb=-tb;
                for(int j=col;j<21;j++)
                    a[i][j]=((a[i][j]*ta)%2-(a[k][j]*tb)%2+2)%2;
            }
        }
    }
    for(int i=0,j;i<20;i++){
        if(!a[i][i]){
            for(j=i+1;j<20;j++)
                if(a[i][j])break;
            if(j==20)break;
            for(int r=0;r<20;r++)swap(a[r][i],a[r][j]);
        }
    }
    int mn=INF;
    for(int j=0;j<(1<<(20-k));j++){
        for(int i=0;i<(20-k);i++)
            if(j&(1<<i))x[20-1-i]=1;
            else x[20-1-i]=0;
        for(int i=k-1;i>=0;i--){
            int tmp=a[i][20]%2;
            for(int j=i+1;j<20;j++)
                if(a[i][j])tmp=(tmp-a[i][j]*x[j]%2+2)%2;
            x[i]=(tmp/a[i][i])%2;
        }
        int tmp=0;
        for(int i=0;i<20;i++)tmp+=x[i];
        mn=min(mn,tmp);
        if(mn==0)break;
    }
    return mn;
}
int main(){
    freopen("Cola.txt","r",stdin);
    for(int i=0;i<20;i++){//枚举对每个数字进行操作 
        scanf("%d",&a[i][20]);
        a[i][i]=1;
        if(i>0)a[i-1][i]=1;
        if(i<19)a[i+1][i]=1;
    }
    printf("%d",guass());
}
100分 高斯消元+枚举变元

 

posted @ 2017-12-22 14:15  Echo宝贝儿  阅读(120)  评论(0编辑  收藏  举报