这道题用了状态压缩。
状态压缩常常用在DP中,而这道题是搜索做的,有些意思。
这道题其实可以看作在一个大矩阵中找一个最大的小正方形阵,二维需要加一重搜索,如果像http://acm.pku.edu.cn/JudgeOnline/problem?id=2441 Arrange the bulls一样,就不用再搜了。
#include
<
iostream
>
#define M 37
using namespace std;
int table[M][M] = { 0 },n;
long long state[M] = { 0 };
int bitcnt[ 0x11ffff + 1 ] = { 0 };
int calbit( long long s)
{
return bitcnt[s & 0x11ffff ] + bitcnt[s >> 18 ];
}
bool dfs( int i, int l, long long s, int len)
{
while (i <= 36 && state[i] == 0 )
++ i;
if (i > 36 && l > 0 ) return false ;
if (l == 0 )
{
return calbit(s) != 36 && calbit(s) >= len;
}
if (calbit(s) < len) return false ;
return dfs(i + 1 ,l,s,len) || dfs(i + 1 ,l - 1 ,s & state[i],len);
}
int main()
{
int nCase,i,s,t,j;
for (i = 1 ;i <= 0x11ffff ;i ++ )
{
int cnt = 0 ;
j = i;
while (j)
{
if ((j & 0x01 ) == 1 ) ++ cnt;
j >>= 1 ;
}
bitcnt[i] = cnt;
}
cin >> nCase;
while (nCase -- )
{
cin >> n;
memset(table, 0 , sizeof (table));
memset(state, 0 , sizeof (state));
state[ 0 ] = (1LL << 36 ) - 1 ;
for (i = 0 ;i < n;i ++ )
{
cin >> s >> t;
table[s][t] = 1 ;
}
for (i = 1 ;i <= 36 ;i ++ )
{
for (j = 1 ;j <= 36 ;j ++ )
{
state[i] <<= 1 ;
if (table[i][j] == 1 ) state[i] |= 0x01 ;
}
}
for (j = 2 ;j <= n;j ++ )
{
if (dfs( 1 ,j,state[ 0 ],j) == false )
break ;
}
cout << j - 1 << endl;
}
}
#define M 37
using namespace std;
int table[M][M] = { 0 },n;
long long state[M] = { 0 };
int bitcnt[ 0x11ffff + 1 ] = { 0 };
int calbit( long long s)
{
return bitcnt[s & 0x11ffff ] + bitcnt[s >> 18 ];
}
bool dfs( int i, int l, long long s, int len)
{
while (i <= 36 && state[i] == 0 )
++ i;
if (i > 36 && l > 0 ) return false ;
if (l == 0 )
{
return calbit(s) != 36 && calbit(s) >= len;
}
if (calbit(s) < len) return false ;
return dfs(i + 1 ,l,s,len) || dfs(i + 1 ,l - 1 ,s & state[i],len);
}
int main()
{
int nCase,i,s,t,j;
for (i = 1 ;i <= 0x11ffff ;i ++ )
{
int cnt = 0 ;
j = i;
while (j)
{
if ((j & 0x01 ) == 1 ) ++ cnt;
j >>= 1 ;
}
bitcnt[i] = cnt;
}
cin >> nCase;
while (nCase -- )
{
cin >> n;
memset(table, 0 , sizeof (table));
memset(state, 0 , sizeof (state));
state[ 0 ] = (1LL << 36 ) - 1 ;
for (i = 0 ;i < n;i ++ )
{
cin >> s >> t;
table[s][t] = 1 ;
}
for (i = 1 ;i <= 36 ;i ++ )
{
for (j = 1 ;j <= 36 ;j ++ )
{
state[i] <<= 1 ;
if (table[i][j] == 1 ) state[i] |= 0x01 ;
}
}
for (j = 2 ;j <= n;j ++ )
{
if (dfs( 1 ,j,state[ 0 ],j) == false )
break ;
}
cout << j - 1 << endl;
}
}
关于状态压缩DP的题目,http://acm.pku.edu.cn/JudgeOnline/problem?id=1038 Bugs Integrated,inc.在刘汝佳的书上有解答,还有著名的“炮兵阵地”一题,及Hamilton路,TSP问题(http://acm.pku.edu.cn/JudgeOnline/problem?id=2288 Islands and Bridges)等。
基本思想就是“状态压缩”,通常是位压缩,涉及位的运算,通常复杂度会比较高(指数级)。
贴一下炮兵阵地的代码:
#include
<
iostream
>
#define N 100
#define M 10
#define MAXSTATE 59049
using namespace std;
int mi[] = { 1 , 3 , 9 , 27 , 81 , 243 , 729 , 2187 , 6561 , 19683 };
int cannon[N + 1 ][MAXSTATE] = { 0 },maxState,mV = 0 ; // canno[i][j]--the i row in state j(old state, i-1 row more accurately) hold that many
char deploy[N][M] = { 0 };
int m,n,re =- 1 ;
void input()
{
int i,j;
cin >> n >> m;
for (i = 0 ;i < n;i ++ )
{
for (j = 0 ;j < m;j ++ )
cin >> deploy[i][j];
}
maxState = mi[m - 1 ] * 3 ;
}
int a[M],cannonAdd; // to record state in 3.
void decode( int s)
{
int i;
for (i = 0 ;i < m; ++ i)
{
a[i] = s % 3 ;
s /= 3 ;
}
}
int encode()
{
int s = 0 ;
for ( int i = 0 ;i < m;i ++ )
{
s += a[i] * mi[i];
}
return s;
}
void place ( int i, int j, int org) // place canno in i row ,from j col, current bit is s
{
if (j == m)
{
int s = encode();
if (cannon[i][org] + cannonAdd > cannon[i + 1 ][s])
{
cannon[i + 1 ][s] = cannon[i][org] + cannonAdd;
if (cannon[i + 1 ][s] > mV)
{
mV = cannon[i + 1 ][s];
}
}
return ;
}
if (a[j] > 0 ) // cannot place
{
-- a[j];
place(i,j + 1 ,org);
++ a[j];
}
else
{
place(i,j + 1 ,org);
if (deploy[i][j] == ' P ' && a[j - 1 ] != 2 && a[j - 2 ] != 2 )
{
a[j] = 2 ;
++ cannonAdd;
place(i,j + 1 ,org);
a[j] = 0 ;
-- cannonAdd;
}
}
}
void solve()
{
int i,j;
for (i = 0 ;i < n;i ++ )
{
for (j = 0 ;j < maxState;j ++ )
{
if (cannon[i][j] + 10 < mV) continue ;
decode(j);
cannonAdd = 0 ;
place(i, 0 ,j);
}
}
}
int main()
{
input();
solve();
cout << mV << endl;
return 0 ;
}
#define N 100
#define M 10
#define MAXSTATE 59049
using namespace std;
int mi[] = { 1 , 3 , 9 , 27 , 81 , 243 , 729 , 2187 , 6561 , 19683 };
int cannon[N + 1 ][MAXSTATE] = { 0 },maxState,mV = 0 ; // canno[i][j]--the i row in state j(old state, i-1 row more accurately) hold that many
char deploy[N][M] = { 0 };
int m,n,re =- 1 ;
void input()
{
int i,j;
cin >> n >> m;
for (i = 0 ;i < n;i ++ )
{
for (j = 0 ;j < m;j ++ )
cin >> deploy[i][j];
}
maxState = mi[m - 1 ] * 3 ;
}
int a[M],cannonAdd; // to record state in 3.
void decode( int s)
{
int i;
for (i = 0 ;i < m; ++ i)
{
a[i] = s % 3 ;
s /= 3 ;
}
}
int encode()
{
int s = 0 ;
for ( int i = 0 ;i < m;i ++ )
{
s += a[i] * mi[i];
}
return s;
}
void place ( int i, int j, int org) // place canno in i row ,from j col, current bit is s
{
if (j == m)
{
int s = encode();
if (cannon[i][org] + cannonAdd > cannon[i + 1 ][s])
{
cannon[i + 1 ][s] = cannon[i][org] + cannonAdd;
if (cannon[i + 1 ][s] > mV)
{
mV = cannon[i + 1 ][s];
}
}
return ;
}
if (a[j] > 0 ) // cannot place
{
-- a[j];
place(i,j + 1 ,org);
++ a[j];
}
else
{
place(i,j + 1 ,org);
if (deploy[i][j] == ' P ' && a[j - 1 ] != 2 && a[j - 2 ] != 2 )
{
a[j] = 2 ;
++ cannonAdd;
place(i,j + 1 ,org);
a[j] = 0 ;
-- cannonAdd;
}
}
}
void solve()
{
int i,j;
for (i = 0 ;i < n;i ++ )
{
for (j = 0 ;j < maxState;j ++ )
{
if (cannon[i][j] + 10 < mV) continue ;
decode(j);
cannonAdd = 0 ;
place(i, 0 ,j);
}
}
}
int main()
{
input();
solve();
cout << mV << endl;
return 0 ;
}