HDU 5163 状压DP

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;
}

你可能感兴趣的:(HDU 5163 状压DP)