hdu2167 http://acm.hdu.edu.cn/showproblem.php?pid=2167
给定一个N*N的板子,里面有N*N个数字,选中一些数字,使得和最大
要求任意两个选中的数字不相邻,相邻包括上下,左右和对角线相邻。
由于N<=15,用程序判断了一下,每一行的有效状态<1600个,如果记录这些状态,然后每一行枚举当前行的上一行的状态那么极端下有1600*1600*15的复杂度,TLE
所以卡在这里很久,想不到怎么优化。 然后看了别人的代码知道了用邻接表存储哪两个状态是相容的。这样就不用枚举那么多了。所以就过了。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <sstream> 5 using namespace std; 6 int matrix[15][15]; 7 int dp[1<<15][15],situation[1600],bit[15],head[1000000],e; 8 struct node 9 { 10 int v,next; 11 }g[1000000];; 12 int max(const int &a, const int &b) 13 { 14 return a < b ? b : a; 15 } 16 17 void addEdge(int u, int v) 18 { 19 g[e].v = v; 20 g[e].next = head[u]; 21 head[u] = e++; 22 } 23 int count(int i, int ss, int n)//计算状体第i行的状态s所取的数的和 24 { 25 int ret = 0; 26 int j = 0; 27 for(j=0; j<n; ++j) 28 { 29 if(bit[j] & ss) 30 ret += matrix[i][j]; 31 } 32 return ret; 33 } 34 bool check(int s, int ss,int n)//检查s和ss是否可容 35 { 36 37 if(s&ss) return false; 38 if((s<<1)&ss) return false; 39 if((s>>1)&ss) return false; 40 return true; 41 } 42 int main() 43 { 44 int n,i,j,m,s,ss; 45 char str[100]; 46 bit[i=0] = 1; 47 for(i=1; i<15; ++i) 48 bit[i] = bit[i-1]<<1; 49 m = 1<<15; 50 for(i=0,j=0; i<m; ++i) 51 if(!(i&(i<<1)))//求出有效的状态 52 situation[j++]= i; 53 while(gets(str)) 54 { 55 memset(dp,0,sizeof(dp)); 56 e = 0; 57 memset(head,-1,sizeof(head)); 58 n = 0; 59 do 60 { 61 j = 0; 62 stringstream scin(str); 63 while(scin>>matrix[n][j]) j++; 64 n++; 65 gets(str); 66 if(str[0]=='