woj1537&&woj1538(递推)

链接:点击打开链接

题意:有n堆石头,每拿一堆,所有石头的a值都减去自身的b,求能够到拿的a的和的最大值

代码:

#include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <iostream>
 #include <algorithm>
 using namespace std;
struct node{
     long long a,b,v;
     friend bool operator<(node x,node y){
         return x.v>y.v;
     }
 }s[1005];
int main(){                                     //因为第i次取第j个物品,所获得的价值
     long long n,i,j,ans,sum;                   //为s[j].a-i*s[j].b,因此第i次取得时
     while(scanf("%lld",&n)!=EOF&&n){           //候取s[j].a-i*s[j].b值最大的i个即可
         for(i=0;i<n;i++)
         scanf("%lld%lld",&s[i].a,&s[i].b);
         ans=0;
         for(i=1;i<=n;i++){
             for(j=0;j<n;j++)
             s[j].v=s[j].a-i*s[j].b;
             sort(s,s+n);
             sum=0;
             for(j=1;j<=i;j++)
             sum+=s[j-1].v;
             ans=max(ans,sum);                  //比较哪一次取出最大值
         }
         printf("%lld\n",ans);
     }
     return 0;
 }


链接:点击打开链接

题意:有n堆石头,每拿一堆,没有被拿的石头堆的a都要减去自身的b,求能够拿到的a的和的最大值

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
    int a,b;
    friend bool operator <(node x,node y){
        return x.b>y.b;                         //让b值大的先被抽取
    }
}s[1005];
int dp[1005][1005];
int main(){                                     //因为这个题与上一个题的区别
    int n,i,j,ans;                              //在于是剩下的物品减去自身的b[i]
    while(scanf("%d",&n)!=EOF&&n){              //所以无法直接确定每次选取哪一个
       ans=0;                                   //所以需要用动态规划
       memset(dp,0,sizeof(dp));
       for(i=1;i<=n;i++)
       scanf("%d%d",&s[i].a,&s[i].b);
       sort(s+1,s+n+1);                         //因为第几次被抽取会影响自身的价值,
       for(i=1;i<=n;i++)                        //因此需要排序
       for(j=i;j>=1;j--)                        //dp[i][j]代表前i次中抽取j个
       dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+s[i].a-s[i].b*(j-1));
       for(i=1;i<=n;i++)
       ans=max(ans,dp[n][i]);
       printf("%d\n",ans);
    }
    return 0;
}


 

你可能感兴趣的:(woj1537&&woj1538(递推))