ZOJ 3755 Mines(状压dp)

Mines


Time Limit: 2 Seconds      Memory Limit: 65536 KB


As a small-game fan, Flandre loves playing the Mine-sweeping very much. He spends 23 hours playing the lowest level of Mine-sweeping every day. 
One day, when Flandre is playing Mine-sweeping, a strange idea comes to him: 
"Can I just calculate the minimum number of the mine in current state of the game ?" 

mines.png

To simplify this problem, we suppose the map is a N*(M*2+1) matrix and there are some mines in the grids of odd columns. You have got all the messages about the even columns which are represented as a N * Mnumber matrix. 
For example: N = 3, M = 2(# represent the mines, number means how many mines around it) 
# 2 1 2 # 
2 4 # 3 0 
# 3 # 2 0 
the messages about the even columns are: 
2 2 
4 3 
3 2 
Your task is to calculate the minimum number of mines with the messages matrix.

Input

There are multiple test cases. For each test case: 
The first line contains two integers N(1≤ N≤ 10), M(1≤ M≤ 10) 
Then followed by N lines, each line contain M integers represent the messages matrix. 
Process to the end of input.

Output

For each the case, print the minimum number of mines.

Sample Input

3 2
2 2
4 3
3 2

Sample Output

4

题意:

有一个n*(2*m+1)  (n,m<=10)的网格,只有奇数列有地雷,根据扫雷的规则,现在给你所有偶数列的数字,问你这个网格至少含有多少个地雷。

思路:

按列计算太麻烦,我们转置成行数字(实际上一样,只是更方便计算)。

由于每个数字都不会超过6,我们可以直接用十进制累加起来存到数组里,对这些数字做一个hash。

我们枚举上一行zt1和下一行zt2的地雷状态(1表示有雷,0表示没雷),计算一下这两个状态对应这一行的数字。

如果这个数字正好出现了,那么我们就把zt2加入对应hash下标的vector[zt1]里。

这样在进行状压dp直接从vector中的状态进行转移即可。

注意第一行状态的预处理。(1A有些小激动)

代码:

#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
using namespace std;
const int maxn=11;
const ll mo=1e8;
int n,m,q,mm;
int a[maxn][maxn];
vector<int>vc[maxn][1025];
int dp[maxn][1025];
pair<ll,int>hs[maxn];
int mp[maxn],up[maxn][1025];
int c[1025];
int cnt;
ll cal(int x,int y,int i)
{
    i=(1<<i);
    ll sum=0;
    if(x&i) sum++;
    if((x<<1)&i) sum++;
    if((x>>1)&i) sum++;
    if(y&i) sum++;
    if((y<<1)&i) sum++;
    if((y>>1)&i) sum++;
    return sum;
}
int fcount(int x)
{
    int sum=0;
    while(x)
    {
        x&=(x-1);
        sum++;
    }
    return sum;
}
void init()
{
    rep(i,0,mm)
    rep(j,0,mm)
    {
        pair<ll,int> x;
        x.first=0;x.second=0;
        rep(k,0,m-1)
        {
            x.first=x.first*10+cal(i,j,k);
        }
        int pos=lower_bound(hs+1,hs+1+n,x)-hs;
        if(pos==n+1) continue;
        if(hs[pos].first==x.first)
        vc[mp[hs[pos].second]][i].push_back(j);
    }
}
int main()
{
    rep(i,0,1024)
    c[i]=fcount(i);
    int T,cas=1;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        cnt=0;
        rep(i,0,n-1)
        rep(j,1,m) scanf("%d",&a[j][i]);
        swap(n,m);
        mm=(1<<m)-1;
        rep(i,0,n)
        rep(j,0,mm)
        {
            vc[i][j].clear();
            dp[i][j]=inf;
        }
        rep(i,1,n)
        {
            ll tmp=0;
            rep(j,0,m-1)
            {
                tmp=tmp*10+(ll)a[i][j];
            }
            hs[i].first=tmp;
            hs[i].second=i;
        }
        sort(hs+1,hs+n+1);
        rep(i,1,n)
        {
            if(i==1||hs[i].first!=hs[i-1].first)
            mp[hs[i].second]=i;
            else mp[hs[i].second]=mp[hs[i-1].second];
        }
        init();

        rep(i,0,mm)
        {
            if(vc[mp[1]][i].size())
            dp[0][i]=c[i];
        }
        rep(i,1,n)
        rep(j,0,mm)
        up[i][j]=vc[mp[i]][j].size()-1;

        rep(i,1,n)
        {
            rep(j,0,mm)
            if(dp[i-1][j]!=inf){
                rep(k,0,up[i][j])
                {
                    int nw=vc[mp[i]][j][k];
                    dp[i][nw]=min(dp[i][nw],dp[i-1][j]+c[nw]);
                }
            }
        }
        int ans=inf;
        rep(i,0,mm)
        ans=min(ans,dp[n][i]);
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/89228221
ZOJ