翻转--开关问题

来源:互联网 发布:我要自学网单片机 编辑:程序博客网 时间:2024/06/06 03:48

详情见挑战p150-156


poj 3276


#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

const int maxn =5000 + 5;

int dir[maxn];

int f[maxn];//f[i] = f[i,i + k - 1]是否翻转

int n;


int cal(int k)

{

    memset(f, 0,sizeof(f));

    int res =0;

    int sum =0;

    for (int i =0; i + k <= n; i ++) {

        if((dir[i] + sum) %2 == 1)

        {

            res ++;

            f[i] = 1;

        }

        sum += f[i];

        if(i - k +1 >= 0)

            sum -= f[i - k + 1];

    }

    for (int i = n - k +1; i < n; i ++) {

        if((dir[i] + sum) %2 == 1)return -1;

        if(i - k +1 >= 0) sum -= f[i - k +1];

    }

    return res;

}

void solve()

{

    int K =1,M = n;//ans

    int m;

    for (int k =1; k <= n; k ++) {

        m = cal(k);

        if(m >=0 && M > m)

        {

            K = k;

            M = m;

        }

    }

    printf("%d %d\n",K,M);

}

int main()

{

    scanf("%d",&n);

    getchar();

    char c;

    for (int i =0; i < n; i ++) {

        scanf("%c%*c",&c);

        if(c =='F') dir[i] = 0;//要求全部转为0

        else dir[i] =1;

    }

    solve();

    return0;

}


poj3279


#include <iostream>

#include <cstdio>

#include <cstring>

using namespacestd;

const int maxn =18;

int mp[maxn][maxn];

int m,n;

int cp[maxn][maxn];//保存操作

int best[maxn][maxn];


const int dir[5][2] = {{0,0},{1,0},{-1,0},{0,1},{0,-1}};


void flip(int x,int y)

{

    int tx,ty;

    for (int i =0; i < 5; i ++) {

        tx = x + dir[i][0];

        ty = y + dir[i][1];

        if(tx >=0 && ty >= 0 && tx <m && ty < n){

            cp[tx][ty] = !cp[tx][ty];

        }

    }

}

int get(int x,int y)

{

    int c =mp[x][y];

    int tx,ty;

    for (int i =0; i < 5; i ++) {

        tx = x + dir[i][0];

        ty = y + dir[i][1];

        if(tx >=0 && ty >= 0 && tx <m && ty < n)

        {

            c +=cp[tx][ty];//虽然从左上到右下的顺序翻转,但是一开始初始化为0,所以还没有翻转的并不影响

        }

    }

    return c %2;

}

int cal()

{

    for (int i =1; i < m; i ++) {

        for (int j =0; j < n; j ++) {

            if(get(i -1,j) == 1)cp[i][j] = 1;

        }

    }

    for (int j =0; j < n; j ++) {

        if(get(m -1,j) == 1)return -1;

    }

    int res =0;

    for (int i =0; i < m; i ++) {

        for (int j =0; j < n; j ++) {

            res += cp[i][j];

        }

    }

    return res;

}

void solve()

{

    int res = -1;

    //写一个n个数的全排列

    for (int i =0; i < (1 <<n); i ++) {

        int t = i;

        memset(cp,0, sizeof(cp));

        for (int j =0; j < n && t;j ++) {

            cp[0][j] = (i >> j) &1;

        }

        int num =cal();

        if(num >0 && (res < 0 || num < res))

        {

            res = num;

            memcpy(best,cp, sizeof(cp));

        }

    }

    if(res <0) printf("IMPOSSIBLE\n");

    else {

        for (int i =0; i < m; i ++) {

            for (int j =0; j < n; j ++) {

                printf("%d",best[i][j]);

                if(j ==n - 1)printf("\n");

                elseprintf(" ");

            }

        }

    }

}


int main()

{

    cin >>m >> n;

    for (int i =0; i < m; i ++) {//mn

        for(int j =0;j < n;j ++)

            scanf("%d",&mp[i][j]);//要求全部翻转到0

    }

    solve();

    return0;

}



原创粉丝点击