题目意思:给定N个数,在给定M个数,现在在N中取数,满足取到得数任意两者之差都不等与M个数中的任意一个。。求最多取多少个数。
思路:把有冲突的数之间连一条边(这样出来竟然没环,而是数,太神奇了)
然后进行树形dp
f[i][0]表示第i个节点不取取得的最大个数
f[i][1]则表示取
f[i][0] = sigma(max(f[j][0],f[j][1]));
f[i][1]= sigma(f[j][0]);
j为i的子树。。
1 /* 2 Time:2013-03-11 09:23:07 3 State:Accepted 4 */ 5 #include <iostream> 6 #include <cstring> 7 #include <cstdlib> 8 #include <cstdio> 9 #include <algorithm> 10 #include <cmath> 11 using namespace std; 12 int n, m , f[210][3], map[210][210] , a[210] , b[210]; 13 14 void init(){ 15 memset(map, 0 , sizeof(map)); 16 memset(f , 0 , sizeof(f)); 17 for (int i = 1; i <= n; ++i) 18 scanf("%d", &a[i]); 19 for (int i = 1; i <= m ;++i) 20 scanf("%d", &b[i]); 21 for (int i = 1; i < n; ++i) 22 for (int j = i + 1 ; j <= n; ++j) 23 for (int k = 1; k <= m; ++k ) 24 if (a[i]-a[j] == b[k] || a[j]-a[i] == b[k]) 25 map[i][j] = map[j][i] = 1; 26 27 28 } 29 30 int dp(int fa ,int x , int k){ 31 if (f[x][k]) return f[x][k]; 32 int temp = 0; 33 for (int y = 1; y <= n ; ++y) 34 if (fa != y && map[x][y]) 35 if (k == 0) temp += max(dp(x , y , 0), dp(x, y, 1)); 36 else temp += dp(x, y, 0); 37 temp += a[x]*k; 38 f[x][k] = temp; 39 return temp; 40 } 41 42 int main(){ 43 freopen("poj1770.in","r",stdin); 44 freopen("poj1770.out","w",stdout); 45 while (scanf("%d%d" , &n , &m)!=EOF && n) 46 { 47 init(); 48 printf("%d\n",max(dp(-1, 1, 0), dp(-1, 1, 1))); 49 } 50 }