这题按行(M)来dp
因为在跟新第i行的时候,与第i-1和i-2行的状态有关,所有要有一维是来记录之前2行的
因为M只有10,所以呢可以用状态压缩来表示该格有无障碍物
第i-1行如果有障碍物的话,不用考虑第i-2行 所以每格有3中状态
A 的前两行就是 0
B 的前两行 1
c 为2
这样做的好处就是 等等更新的时候比较方便
然后每次就是从i-1的某种状态来搜出所有的对应的i行的状态
最开始状态就是只有 全2的情况
这里我有个问题有点想不通,就是黑书上说算法复杂度是 nm3^m 当时我觉得在 从上一种状态搜所有的新状态时要搜3^m次 所以复杂度应该是 n*3^m *3^m啊 不解啊啊啊啊
希望有谁知道请告诉我一下,感激不尽,谢谢
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int pows[11] = { 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049 };
int maps[160][11];
int N, M, K;
int dp[2][60000];
int nowstatu[11], prestatu[11];
int nowr;
int pp[11];
void getstatu( int k, int num ){
for( int i = 1; i <= M; i++ ){
prestatu[i] = num % 3;
if( prestatu[i] ){
nowstatu[i] = prestatu[i] - 1;
}else{
nowstatu[i] = 0;
}
if( maps[k][i] ){
nowstatu[i] = 2;
}
num /= 3;
}
}
int getnum(){
int ans = 0;
for( int i = 1; i <= M; i++ ){
ans += nowstatu[i] * pows[i-1];
}
return ans;
}
void DFS( int now, int pos, int sum ){
if( pos > M ){
return;
}
int st;
st = getnum();
dp[now][st] = max( dp[now][st], sum );
DFS( now, pos + 1, sum );
if( prestatu[pos] == 0 && prestatu[pos-1] == 0 && maps[nowr][pos] == 0 && maps[nowr][pos-1] == 0 && pp[pos] == 0 && pp[pos-1] == 0 ){
nowstatu[pos] = nowstatu[pos-1] = 2;
pp[pos] = pp[pos-1] = 1;
st = getnum();
dp[now][st] = max( dp[now][st], sum + 1 );
DFS( now, pos + 1, sum + 1 );
pp[pos] = pp[pos-1] = 0;
nowstatu[pos] = nowstatu[pos-1] = 0;
}
if( pos >= 3 && prestatu[pos] <= 1 && prestatu[pos-1] <= 1 && prestatu[pos-2] <= 1
&& maps[nowr][pos] == 0 && maps[nowr][pos-1] == 0 && maps[nowr][pos-2] == 0
&& pp[pos] == 0 && pp[pos-1] == 0 && pp[pos-2] == 0 ){
int a = nowstatu[pos], b = nowstatu[pos-1], c = nowstatu[pos-2];
nowstatu[pos] = nowstatu[pos-1] = nowstatu[pos-2] = 2;
pp[pos] = pp[pos-1] = pp[pos-2] = 1;
st = getnum();
dp[now][st] = max( dp[now][st], sum + 1 );
DFS( now, pos + 1, sum + 1 );
pp[pos] = pp[pos-1] = pp[pos-2] = 0;
nowstatu[pos] = a;
nowstatu[pos-1] = b;
nowstatu[pos-2] = c;
}
return;
}
int main(){
int T;
cin >> T;
while( T-- ){
cin >> N >> M >> K;
memset( maps, 0, sizeof( maps ) );
for( int i = 0; i < K; i++ ){
int temp1, temp2;
cin >> temp1 >> temp2;
maps[temp1][temp2] = 1;
}
memset( dp, -1, 60000 * sizeof( int ) );
int maxr = 0;
for( int i = 0; i < M; i++ ){
maxr += 2 * pows[i];
}
dp[0][maxr] = 0;
int now = 1, pre = 0;
for( int i = 1; i <= N; i++ ){
memset( dp[now], -1, 60000 * sizeof( int ) );
for( int j = 0; j <= maxr; j++ ){
if( dp[pre][j] != -1 ){
getstatu( i, j );
nowr = i;
memset( pp, 0, sizeof( pp ) );
int st = getnum();
dp[now][st] = max( dp[now][st], dp[pre][j] );//注意这里
DFS( now, 2, dp[pre][j] );
}
}
now ^= 1;
pre ^= 1;
}
int ans = -1;
for( int i = 0; i <= maxr; i++ ){
ans = max( ans, dp[pre][i] );
}
cout << ans << endl;
}
return 0;
}