天天看點

HDU 2119 Matrix

Problem Description

Give you a matrix(only contains 0 or 1),every time you can select a row or a column and delete all the '1' in this row or this column .

Your task is to give out the minimum times of deleting all the '1' in the matrix.

Input

There are several test cases.

The first line contains two integers n,m(1<=n,m<=100), n is the number of rows of the given matrix and m is the number of columns of the given matrix.

The next n lines describe the matrix:each line contains m integer, which may be either ‘1’ or ‘0’.

n=0 indicate the end of input.

Output

For each of the test cases, in the order given in the input, print one line containing the minimum times of deleting all the '1' in the matrix.

Sample Input

3 3 
0 0 0
1 0 1
0 1 0
0      

Sample Output

2

可以直接跑dlx重複覆寫,不過必須要剪枝,數量不會大于行或列的較小值。

#include<cstdio>
#include<vector>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll maxn = 105;
int T, n, m, x, y, t, tot, a[maxn][maxn];

inline void read(int &ret)
{
  char c;
  do {
    c = getchar();
  } while (c < '0' || c > '9');
  ret = c - '0';
  while ((c = getchar()) >= '0' && c <= '9')
    ret = ret * 10 + (c - '0');
}

struct DLX
{
#define maxn 50005
#define F(i,A,s) for (int i=A[s];i!=s;i=A[i])
  int L[maxn], R[maxn], U[maxn], D[maxn];
  int row[maxn], col[maxn], ans[maxn], cnt[maxn];
  int n, m, num, sz;

  void add(int now, int l, int r, int u, int d, int x, int y)
  {
    L[now] = l; R[now] = r; U[now] = u;
    D[now] = d;   row[now] = x;  col[now] = y;
  }
  void reset(int n, int m)
  {
    num = 0x7FFFFFFF;
    this->n = n; this->m = m;
    for (int i = 0; i <= m; i++)
    {
      add(i, i - 1, i + 1, i, i, 0, i);
      cnt[i] = 0;
    }
    L[0] = m;   R[m] = 0;   sz = m + 1;
  }
  void insert(int x, int y)
  {
    int ft = sz - 1;
    if (row[ft] != x)
    {
      add(sz, sz, sz, U[y], y, x, y);
      U[D[sz]] = sz; D[U[sz]] = sz;
    }
    else
    {
      add(sz, ft, R[ft], U[y], y, x, y);
      R[L[sz]] = sz; L[R[sz]] = sz;
      U[D[sz]] = sz; D[U[sz]] = sz;
    }
    ++cnt[y]; ++sz;
  }

  //精确覆寫
  void remove(int now)
  {
    R[L[now]] = R[now];
    L[R[now]] = L[now];
    F(i, D, now) F(j, R, i)
    {
      D[U[j]] = D[j];
      U[D[j]] = U[j];
      --cnt[col[j]];
    }
  }
  void resume(int now)
  {
    F(i, U, now)  F(j, L, i)
    {
      D[U[j]] = j;
      U[D[j]] = j;
      ++cnt[col[j]];
    }
    R[L[now]] = now;
    L[R[now]] = now;
  }
  bool dfs(int x)
  {
    //if (x + A() >= num) return;
    if (!R[0]) { num = min(num, x); return true; }
    int now = R[0];
    F(i, R, 0) if (cnt[now]>cnt[i]) now = i;
    remove(now);
    F(i, D, now)
    {
      ans[x] = row[i];
      F(j, R, i) remove(col[j]);
      if (dfs(x + 1)) return true;
      F(j, L, i) resume(col[j]);
    }
    resume(now);
    return false;
  }
  //精确覆寫

  //重複覆寫
  void Remove(int now)
  {
    F(i, D, now)
    {
      L[R[i]] = L[i];
      R[L[i]] = R[i];
    }
  }
  void Resume(int now)
  {
    F(i, U, now) L[R[i]] = R[L[i]] = i;
  }
  int vis[maxn];
  int flag[maxn];
  int A()
  {
    int dis = 0;
    F(i, R, 0) vis[i] = 0;
    F(i, R, 0) if (!vis[i])
    {
      dis++;  vis[i] = 1;
      F(j, D, i) F(k, R, j) vis[col[k]] = 1;
    }
    return dis;
  }
  void Dfs(int x)
  {
    if (!R[0]) num = x;
    else if (x + A()<num)
    {
      int now = R[0];
      F(i, R, 0) if (cnt[now]>cnt[i]) now = i;
      F(i, D, now)
      {
        Remove(i); F(j, R, i) Remove(j);
        Dfs(x + 1);
        F(j, L, i) Resume(j); Resume(i);
      }
    }
  }
  //重複覆寫
}dlx;

int main()
{
  //read(T);
  while (~scanf("%d",&n),n)
  {
    read(m);
    tot=0;
    for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
      {
        read(a[i][j]);
        if (a[i][j]) a[i][j]=++tot;
      }
    dlx.reset(n+m,tot);
    dlx.num=min(n,m);
    for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
        if (a[i][j]) dlx.insert(i,a[i][j]);
    for (int i=1;i<=m;i++)
    {
      int ans=0;
      for (int j=1;j<=n;j++) if (a[j][i]) ans++;
      if (ans==1) continue;
      for (int j=1;j<=n;j++) if (a[j][i]) dlx.insert(n+i,a[j][i]);
    }
    dlx.Dfs(0);
    printf("%d\n",dlx.num);
  }
  return 0;
}