今天做了 poj 1770 题,大意是 对一堆原子进行取舍,使之不能有“危险原子”,求总能量最大。危险原子的定义如下:
1:有两个原子能量相同的。
2:两个原子可以增加或减少一个光子的能量,能够达到相同。
例如:
3 1
2
4
6
2
前三个表示,原子能量。后一个是光子能量。
思路是:树状dp。起初想的是暴搜。但又不知到如何记录就已经走过的节点。因为每个节点是两种状态。可以分别 0,1表示。前不久刚接触树形dp,比较容易联想到。
代码如下:
#include<iostream>
using namespace std;
int d[201][2];
int tu[201][201];
long en[201];
long ph[201];
bool usif[201];
int n,m;
int sovle(int now,int pre,bool flag) ;
{
if(d[now][flag]!=-1)return d[now][flag];
else
if(flag==1) d[now][flag]=en[now];
else d[now][flag]=0;
for(int i=0;i<n;++i)
if(i!=pre&&tu[now][i])
{
if(flag==1) d[now][flag]+=sovle(i,now,0);
else d[now][flag]+=max(sovle(i,now,1),sovle(i,now,0));
}
return d[now][flag];
}
int main()
{
int i,j;
long sum=0;
while(scanf("%d%d",&n,&m)&&n)
{
sum=0;
for(i=0;i<n;++i)
{
scanf("%ld",&en[i]);
sum+=en[i];
}
//printf("%d/n",sum);
for(j=0;j<m;++j)
scanf("%ld",&ph[j]);
memset(tu,0,sizeof(tu));
for(i=0;i<n;++i)
for(j=0;j<n;++j)
for(int k=0;k<m;++k)
{
if(abs(en[i]-en[j])==ph[k]||(i!=j&&en[i]==en[j]));建图,双向的。
{
tu[i][j]=1;
tu[j][i]=1;
break;
}
}
memset(d,-1,sizeof(d));
long temp= max(sovle(0,-1,0),sovle(0,-1,1));;取最大值。
printf("%ld/n",temp);
}
return 0;
}