HDU 5163 状压DP

来源:互联网 发布:win10 软件消失了 编辑:程序博客网 时间:2024/05/29 16:24

HDU 5163
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5613
题意:
给一个矩阵,矩阵的值为原来矩阵此位置所在的九宫格里所有数字和(均为01)
还原出原来的矩阵。
思路:
状压枚举第一列的状态,然后递推后面状态就可以,很简单的模型题。
然而并不知道怎么合法,看到别人有用左上角的g值来推右下角,瞬间感觉智商再一次被碾压……详见代码
原来想合着一起发的,突然发现这题还没人发代码赶紧来一发赚一赚访问量[京都脸]
源码:

#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <string>#include <algorithm>#include <iostream>using namespace std;int g[105][105];int out[105][105];int output[105][105];int n, m;int cal(int i, int j){    int ans = g[i][j];    for(int t1 = -1 ; t1 <= 1 ; t1++){        for(int t2 = -1 ; t2 <= 1 ; t2++){            if(t1 == 1 && t2 == 1) continue;            ans -= out[i + t1][j + t2];        }    }    return ans;}bool check(int i, int j){    int temp = 0;    for(int t1 = -1 ; t1 <= 1 ; t1++){        for(int t2 = -1 ; t2 <= 1 ; t2++){            temp += out[i + t1][j + t2];        }    }    if(temp == g[i][j]) return true;    return false;}bool valid(int s){    if((1 << n) & s) return false;    for(int i = 1 ; i <= m ; i++) out[1][i] = out[n][i] = 0;    for(int i = 2 ; i <= n - 1 ; i++){        if((1 << i) & s) out[i][1] = 1;        else out[i][1] = 0;    }//    printf("s = %d\n");//    for(int i = 0 ; i < n ; i++) printf("%d ", out[i][0]);//    printf("\n");    for(int j = 2 ; j <= m ; j++){        for(int i = 2 ; i <= n - 1 ; i++){            out[i][j] = cal(i - 1, j - 1);            if(out[i][j] > 1 || out[i][j] < 0) return false;        }        for(int i = 1 ; i <= n ; i++){            if(!check(i, j - 1)) return false;        }    }    for(int i = 1 ; i <= n ; i++) if(!check(i, m)) return false;    for(int i = 1 ; i <= n ; i++) for(int j = 1 ; j <= m ; j++) output[i][j] = out[i][j];//    for(int i)    return true;}int main(){//    freopen("HDU 5163.in", "r", stdin);    int T;    scanf("%d", &T);    while(T--){        scanf("%d%d", &n, &m);        memset(g, 0, sizeof(g));        memset(out, 0, sizeof(out));        for(int i = 1 ; i <= n ; i++) for(int j = 1 ; j <= m ; j++) scanf("%d", &g[i][j]);        int ok = 0;        for(int s = 0 ; s < (1 << (n + 1)); s += 4){            if(valid(s)){//                printf("s = %d\n", s);                ok++;            }        }        if(ok == 0) printf("Impossible\n");        else if(ok >= 2) printf("Multiple\n");        else{            for(int i = 1 ; i <= n ; i++){                for(int j = 1 ; j <= m ; j++){                    printf("%d", output[i][j]);                    if(j == m) printf("\n");                    else printf(" ");                }            }        }    }    return 0;}
0 0
原创粉丝点击