atcoder Low Range-Sum Matrix dfs

问题 F: Low Range-Sum Matrix

时间限制: 1 Sec  内存限制: 128 MB
提交: 83  解决: 9
[提交] [状态] [命题人:admin]

题目描述

You received a card at a banquet. On the card, a matrix of N rows and M columns and two integers K and S are written. All the elements in the matrix are integers, and an integer at the i-th row from the top and the j-th column from the left is denoted by Ai,j.

You can select up to K elements from the matrix and invert the sign of the elements. If you can make a matrix such that there is no vertical or horizontal contiguous subsequence whose sum is greater than S, you can exchange your card for a prize.

Your task is to determine if you can exchange a given card for a prize.

 

输入

The input consists of a single test case of the following form.

N M K S
A1,1 A1,2 ... A1,M
:
AN,1 AN,2 ... AN,M
The first line consists of four integers N,M,K and S (1≤N,M≤10,1≤K≤5,1≤S≤106). The following N lines represent the matrix in your card. The (i+1)-th line consists of M integers Ai,1,Ai,2,...,Ai,M(−105≤Ai,j≤105).

 

输出

If you can exchange your card for a prize, print 'Yes'. Otherwise, print 'No'.

 

样例输入

复制样例数据

3 3 2 10
5 3 7
2 6 1
3 4 1

样例输出

Yes

 

提示

The sum of a horizontal contiguous subsequence from A1,1 to A1,3 is 15. The sum of a vertical contiguous subsequence from A1,2to A3,2 is 13. If you flip the sign of A1,2, there is no vertical or horizontal contiguous subsequence whose sum is greater than S.

 

[提交][状态]

题意:在一个矩阵中选出不超过k个数变成其相反数使得这个矩阵中任何水平或垂直的序列和没有超过s的

其实思路很清晰,就是在矩阵中挑k个数,然后check

为了减少复杂度先预处理出哪些行哪些列是不合法的,标记出来,挑选的数只可能在这些行或列中

然后就是考验 dfs 剪枝的时候了

剪枝太少,会t,剪枝顺序不合适,也可能会wa或者re等各种错误

代码:

#include 
 
using namespace std;
typedef long long ll;
const int maxn = 100;
int a[maxn][maxn];
bool row[maxn], col[maxn];
int n, m, s;
 
bool calr(int i) {
    int temp = 0;
    for (int j = 1; j <= m; j++) {
        temp += a[i][j];
        if (temp > s) {
            return true;
        }
        if (temp < 0) temp = 0;
    }
    return false;
}
 
bool call(int i) {
    int temp = 0;
    for (int j = 1; j <= n; j++) {
        temp += a[j][i];
        if (temp > s) {
            return true;
        }
        if (temp < 0) temp = 0;
    }
    return false;
}
 
bool dfs(int x, int y, int k) {
    if (y == m + 1) return dfs(x + 1, 1, k);
    if (x <= n && (a[x][y] <= 0 || (!row[x] && !col[y]))) return dfs(x, y + 1, k);
 
    int cnt1 = 0, cnt2 = 0;
    for (int i = 1; i <= n; i++) {
        if (i < x && row[i]) return false;
        cnt1 += row[i];
    }
    for (int j = 1; j <= m; j++) cnt2 += col[j];
    if (cnt1 > k || cnt2 > k) return false;
    if (cnt1 == 0 && cnt2 == 0) return true;
 
    if (x == n + 1 || k == 0) return false;
 
    if (dfs(x, y + 1, k)) return true;
    if ((row[x] || col[y]) && a[x][y] > 0) {
        bool r = row[x], c = col[y];
        a[x][y] *= -1;
        row[x] = calr(x);
        col[y] = call(y);
        if (dfs(x, y + 1, k - 1)) return true;
        a[x][y] *= -1;
        row[x] = r;
        col[y] = c;
    }
    return false;
}
 
int main() {
    int k;
    scanf("%d%d%d%d", &n, &m, &k, &s);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &a[i][j]);
        }
    }
    for (int i = 1; i <= n; i++) {
        row[i] = calr(i);
    }
    for (int i = 1; i <= m; i++) {
        col[i] = call(i);
    }
    if (dfs(0, 0, k)) puts("Yes");
    else puts("No");
    return 0;
}

 

你可能感兴趣的:(ACM)