题目描述同POJ1192一样繁琐。。。意思很简单,如果两个原子的能量之差刚好是某个光子的能量,那么将会引起爆炸。。现在选取若干个原子,使得他们的能量之和最大,且不发生爆炸。建树方式:如果两个原子能量之差刚好是一个光子的能量,那么连边这样问题就变成了求最大独立集。方程就不在写了。。。具体看程序
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
using std::map ;
using std::vector ;
#define maxn 205
map<int , int> hash ;
int node[maxn] ;
int diff[maxn] ;
vector<int> G[maxn] ;
int dp[maxn][2] ;
bool vis[maxn] ;
int n , m ;
void read(){
hash.clear() ;
for(int i = 0 ; i <= n ; i ++){
G[i].clear() ;
}
memset(dp , 0 , sizeof(dp)) ;
memset(vis , 0 , sizeof(vis)) ;
for(int i = 1 ; i <= n ; i ++){
int a ;
scanf("%d" , &a) ;
hash[a] = i ;
node[i] = a ;
}
for(int i = 1 ; i <= m ; i ++){
scanf("%d" , &diff[i]) ;
}
}
inline int max(int x , int y){
return x > y ? x : y ;
}
void dfs(int v , int f){
for(int i = 0 ; i != G[v].size() ; i ++){
int u = G[v][i] ;
if(u == f)
continue ;
dfs(u , v) ;
dp[v][0] += max(dp[u][1] , dp[u][0]) ;
dp[v][1] += dp[u][0] ;
}
dp[v][1] += node[v] ;
}
void solve(){
//build the tree
for(int i = 1 ; i <= n ; i ++){
for(int j = 1 ; j <= m ; j ++){
if(hash.count( node[i] + diff[j] )){
G[i].push_back(hash[ node[i] + diff[j] ]) ;
}
if(hash.count( node[i] - diff[j] )){
G[i].push_back(hash[ node[i] - diff[j] ]) ;
}
}
}
dfs(1 , -1) ;
printf("%d\n" , max( dp[1][0] , dp[1][1] ) ) ;
}
int main(){
while(scanf("%d%d" , &n , &m) , n + m){
read() ;
solve();
}
return 0 ;
}