poj 3279(翻转问题贪心)

来源:互联网 发布:京东秒杀软件 编辑:程序博客网 时间:2024/06/05 18:31


翻转问题一般是从前面开始贪心,如果是一维的话直接从前面往后贪心,如果是二维的话,就得枚举第一行的状态,然后从第一行往下贪心。


这个题就是二维的开关问题,需要枚举第一行的状态,复杂度为2^n,然后往后遍历贪心。总复杂度为2^n * n*m,因为n < 15 && m < 15,所以能在时限内通过。

PS :要特判n == 1,把他当作一维的来做


Code:


#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn = 10 + 10;#define INF 0x3f3f3f3fint n,m;int a[maxn][maxn];int b[maxn][maxn];void work(int x,int y){    a[x][y] ^= 1;    a[x - 1][y] ^= 1;    a[x + 1][y] ^= 1;    a[x][y - 1] ^= 1;    a[x][y + 1] ^= 1;}int vis[maxn][maxn];int main(){    while( ~ scanf("%d%d",&n,&m))    {        memset(vis,0,sizeof(vis));        for(int i = 1; i <= n; i ++)            for(int j = 1; j <= m; j ++)            scanf("%d",&b[i][j]);        if(n == 1 && m == 1)        {            if(b[1][1] == 1)                puts("1");            else puts("0");            continue;        }        if(n == 1)        {            int ans = 0;            for(int i = 1; i <= n; i ++)                for(int j = 1; j <= m; j ++)                a[i][j] = b[i][j];            for(int j = 1; j < m; j ++)            {                if(a[1][j] == 1)                {                    work(1,j + 1);                    ans ++;                    vis[1][j + 1] = 1;                }            }//            cout << ans << endl;            bool flags = 1;            for(int j = 1; j <= m; j ++)            if(a[1][j] == 1)            {                flags = 0;//                cout << j << endl;                puts("IMPOSSIBLE");                break;            }            if(flags)            for(int j = 1; j <= m; j ++)                printf("%d%c",vis[1][j],j <= m - 1 ? ' ' : '\n');            continue;        }        int ans = INF;        int temp;        for(int k = 0; k < (1 << n); k ++)//枚举第一层的翻转顺序        {            for(int i = 1; i <= n; i ++)                for(int j = 1; j <= m; j ++)                a[i][j] = b[i][j];            int cnt = 0;            memset(vis,0,sizeof(vis));            int temps = 0;            for(int j = 1; j <= n; j ++)            {                if((1 << (j - 1)) & k)                {                    work(1,j),vis[1][j] = 1,cnt ++;                }            }            for(int i = 1; i < n; i ++)            {                for(int j = 1; j <= m; j ++)                {                    if(a[i][j] == 1)                    {                        work(i + 1,j);                        cnt ++;                        vis[i + 1][j] = 1;                    }                }            }            for(int j = 1; j <= m; j ++)            if(a[n][j] == 1)            {                cnt = INF;                break;            }//            cout << cnt << " ";            if(cnt < ans)                ans = cnt,temp = k;        }//        cout << endl;        if(ans == INF)        {            puts("IMPOSSIBLE");            continue;        }        for(int i = 1; i <= n; i ++)            for(int j = 1; j <= m; j ++)            a[i][j] = b[i][j];        memset(vis,0,sizeof(vis));        for(int j = 1; j <= n; j ++)        {            if((1 << (j - 1)) & temp)                work(1,j),vis[1][j] = 1;        }        for(int i = 1; i < n; i ++)        {            for(int j = 1; j <= m; j ++)            {                if(a[i][j] == 1)                {                    work(i + 1,j);                    vis[i + 1][j] = 1;                }            }        }        for(int i = 1; i <= n; i ++)        {            for(int j = 1; j <= m; j ++)            {                printf("%d%c",vis[i][j],j < m ? ' ' : '\n');            }        }    }    return 0;}


原创粉丝点击