pku 1632 Vase Collection

這道題用了狀態壓縮。

狀態壓縮常常用在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;
    }
}

 

關於狀態壓縮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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章