【洛谷 P2080】增进感情(背包DP)
题目背景
小明和小红的感情,是慢慢发展起来的。
题目描述
他们对对方分别有一个好感值。定义两人的亲密程度为两人的好感值之和。
如果他们的亲密程度达到V,则他们将走到一起。他们以后的生活将取决于两人的好感值之差的绝对值,这个值越小,他们的生活将越幸福。
现在,他们对对方的好感值都为0,小明有N件事可以干,每件事可以增加他对小红的好感Ai点,并且增加小红对他的好感Bi点。(可能为负数)
小明可以任选一些事做,请你帮小明求出怎样才能让他们的生活更加幸福(求出两人在一起的前提下,好感值之差的最小绝对值即可)。
输入输出格式
输入格式:
第1行,两个正整数N,V。
之后N行,每行两个空格隔开的整数Ai,Bi。
输出格式:
一行,一个非负整数,表示两人在一起的前提下,好感值之差的最小绝对值。如果无论如何两人也无法在一起,输出-1.
把每件事情好感值之和转换为事情的价值,把差转化为事情的花费,这样问题就成了一个普通的背包DP。因为好感值之差的绝对值最小为0,所以当发现好感值之和大于亲密程度且差的绝对值为0可以直接输出。
1 #include <cstdio> 2 #include <cmath> 3 4 using std::abs; 5 #define INF 0x7ffffff 6 7 int n,vmax,sum,a,b,w[31],v[31],f[6200],ans=INF; 8 #define min(x,y) (abs(x)<abs(y)?x:y) 9 10 int main(void){ 11 scanf("%d%d",&n,&vmax); 12 for(int i=1;i<=n;++i){ 13 scanf("%d%d",&a,&b); 14 w[i]=a+b; 15 v[i]=a-b; 16 if(a+b>0)sum+=a+b; 17 } 18 for(int i=1;i<=sum;++i) 19 f[i]=INF; 20 for(int i=1;i<=n;++i){ 21 for(int j=sum;j>=w[i];--j){ 22 f[j]=min(f[j],f[j-w[i]]+v[i]); 23 if((f[j]==0)&&(j>=vmax)){ 24 printf("0"); 25 return 0; 26 } 27 } 28 } 29 for(int i=vmax;i<=sum;++i) 30 ans=min(ans,abs(f[i])); 31 printf("%d",ans==INF?-1:ans); 32 }