"Compression DP status" artillery positions

Title Description

Here Insert Picture Description

answer

This question is really cancer ...

First observation range to the column is small, this revelation we use state compression algorithm.

We can not pre-processing the digital all horizontal attack each other, it is clear that only a few hundred of these two. Memory array with b.

We observed that if a line can prevent the artillery and the two lines is determined, we set f [ i ] [ j ] [ k ] f[i][j][k] denotes i i status line is b j b_j The first i 1 i-1 line status b k b_k It can be placed up to artillery.

So we set up so that a state is l, there is a state transition equation is obvious: f [ i ] [ j ] [ k ] = m a x ( f [ i ] [ j ] [ k ] , f [ i 1 ] [ k ] [ l ] + c o u n t ( j ) ) f[i][j][k]=max(f[i][j][k],f[i-1][k][l]+count(j))
In this case, we need to consider the state of the transfer restriction conditions equation:

  • Clearly, in order to prevent another attack, we must first meet b [ i ] & b [ i 1 ] = ̸ 0 b[i]\&b[i-1]=\not 0 and b [ i ] & b [ i 2 ] = ̸ 0 b[i]\&b[i-2]=\not 0 .
  • To make both in the plains, to be met a [ i ] p = a [ i ] a[i]|p=a[i] . p { j , k } . p∈\{j,k\}.
  • Then we let f [ 0 ] [ 1 ] [ 1 ] = 0 f[0][1][1]=0 (if b [ 1 ] = 0 b[1]=0 ), the rest is negative infinity. and also, c o u n t ( i ) count(i) represents the number of i is the binary number 1.

code show as below:

#include <bits/stdc++.h>

using namespace std;
const int N = 200;

int n, m, ans = 0, s = 0;
int a[N], f[N][N][N], b[N], c[N];

bool check(int x)
{
	int t[20] = {};
	for (int i=m-1;i>=0;--i) 
	    t[i+1] = x >> i & 1;
	for (int i=3;i<=m;++i) 
	    if (t[i]+t[i-1]+t[i-2] > 1) return 0;
	return 1;
}

bool valid(int x,int y) {
	return (x | a[y]) == a[y];
}

bool safe(int x,int y,int z) {
	return (b[x] & b[y]) == 0 && (b[y] & b[z]) == 0 && (b[x] &b[z]) == 0;
}

int count(int x) {
	int cnt = 0;
	while (x > 0) cnt += x&1, x >>= 1;
	return cnt;
}

int main(void)
{
	freopen("input.in","r",stdin);
	freopen("output.out","w",stdout);
	cin >> n >> m;
	for (int i=1;i<=n;++i)
	{
		int s = 0;
	    for (int j=1;j<=m;++j)
	    {
	    	char c;
	    	cin >> c;
	    	if (c == 'P') s = s<<1|1;
	    	else s = s<<1;
	    }
	    a[i] = s;
	}
	for (int i=0;i<1<<m;++i) 
		if (check(i)) b[++s] = i, c[s] = count(i);
	memset(f,-30,sizeof f);
	f[0][1][1] = 0;
	for (int i=1;i<=n;++i)
	    for (int j=1;j<=s;++j) if (valid(b[j],i))
	        for (int k=1;k<=s;++k) if (valid(b[k],i-1) && (b[j]&b[k]) == 0)
	            for (int l=1;l<=s;++l) if ((b[j]&b[l]) == 0) 
	                f[i][j][k] = max(f[i][j][k],f[i-1][k][l]+c[j]), ans = max(ans,f[i][j][k]);
	cout << ans << endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/Ronaldo7_ZYB/article/details/92716388