hdu1565 用搜索代替枚举找可能状态或者轮廓线解(较优),参考poj2411
这题用直接枚举是超时的,必须要用搜索来搜索出所有可能的状态,然后再进行枚举
这是较慢的做法
/* 方格取数,相邻格子的数不可取,问最多取到的和是什么 有点类似炮兵布阵,先打出所有可能的状态,然后dp[i][j]表示前i行在状态v[j]下的最大和 dp[i][j]由dp[i-1][t]推出,v[t]是和v[j]兼容的状态 */ #include<bits/stdc++.h> using namespace std; int mp[25][25],n,dp[21][200000]; int v[200000],tot; vector<int>sum[25];//sum[i][j]表示第i行在状态v[j]下的和 inline int legal(int j){ if( j&(j<<1) )return false; return true; } inline int cal(int s,int k){//状态s对应的数值 int res=0; for(int i=1;i<=n;i++) if( s&(1<<(i-1)) )res+=mp[k][n-i+1]; return res; } void init(){ tot=0; for(int j=0;j<=(1<<n)-1;j++) if(legal(j))v[tot++]=j; } int main(){ while(cin>>n){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)cin>>mp[i][j]; init(); memset(dp,0,sizeof dp); for(int i=0;i<tot;i++) dp[1][i]=cal(v[i],1); for(int i=2;i<=n;i++) for(int j=0;j<tot;j++){//枚举i行的状态 for(int k=0;k<tot;k++){//枚举k行的状态 if( v[k]&v[j] )continue; dp[i][j]=max(dp[i][j],dp[i-1][k]+cal(v[j],i)); } } int ans=0; for(int i=0;i<tot;i++) ans=max(ans,dp[n][i]); printf("%d\n",ans); } }