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