Problem 1538 - B - Stones II 贪心+DP

还是给你石头n枚,每一枚石头有两个值a和b,每取一个石头,除了这块石头其余所有的石头的a就都减去这个石头的b,问你取了的石头的a的总和最大可以为多少?

先按B从大到小排序

然后DP:

取的话:dp[i][j]=dp[i-1][j-1]+a[i]-b[i]*(j-1) 注意是j-1

不取的话:dp[i][j]=dp[i-1][j];

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define Maxn 1100
struct Inf
{
    int a,b;
}save[Maxn];
LL dp[Maxn][Maxn];
int n;
LL Max(LL a,LL b)
{
    return a>b?a:b;
}
bool cmp(struct Inf a,struct Inf b)
{
    return a.b>b.b;
}
int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);

   while(scanf("%d",&n)&&n)
   {
       for(int i=1;i<=n;i++)
           scanf("%lld%lld",&save[i].a,&save[i].b);
       sort(save+1,save+n+1,cmp);
       for(int i=0;i<=n;i++)
                dp[i][0]=0;
       for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=i;j++)
                dp[i][j]=max(dp[i-1][j-1]+save[i].a-save[i].b*(j-1),dp[i-1][min(j,i-1)]);
               //dp[i][j]=Max(dp[i-1][j],dp[i-1][j+1]+save[i].a-save[i].b*j);
       }
       LL ans=0;
       for(int i=1;i<=n;i++)
        ans=max(ans,dp[n][i]);
       printf("%lld\n",ans);
   }
   return 0;
}
时间: 2024-08-19 13:10:13

Problem 1538 - B - Stones II 贪心+DP的相关文章

贪心+dp

贪心+dp 好多题都是这个思想, 可以说是非常重要了 思想一: 在不确定序列无法dp的情况下, 我们不妨先假设序列已经选定, 而利用贪心使序列达到最优解, 从而先进行贪心排序, 在进行dp选出序列 思想二: 最优解一定满足上一个状态在某 Problem 1 n 座楼房,立于城中. 第 i 座楼,高度 \(h_i\) . 你需要一开始选择一座楼,开始跳楼.在第 座楼准备跳楼需要 的花费.每次可以跳到任何一个还没有跳过的楼上去.但跳楼是有代价的,每次跳到另外一座楼的代价是两座楼高度的差的绝对值,最后

HDU 2830 Matrix Swapping II (DP,最大全1矩阵)

题意  给你一个n*m矩阵  每列都可以随便交换位置   求最优交换后最大的全1子矩阵 又是HDU 1505 1506的变种  但这个更容易了  因为每列都可以交换位置了   那么这一行中所有比i高的都可以与i相邻了  只需要统计这一行有多少个比i高就行了   可以在算出每一行后  把高度大的放前面去  用num[i]记录排序后的列原来的数  这样就有j列比h[i][num[j]]高了  最后的答案也就是max(j*h[i][num[j]]) #include<cstdio> #include

LeetCode &quot;Palindrome Partition II&quot; - Double DP

A so juicy and interesting problem! Recommend to everyone! A final solution may not jump into your mind immediately, of course, DP is not a trivial topic. So let's go step by step - it is more interesting that how you get to destination than destinat

hdu1207 汉诺塔II 简单dp

本文出自:http://blog.csdn.net/svitter 题意:汉诺塔,多了一根柱子,问你寻找最快的移动次数. dp [ n ] = dp [ n - j ] * 2 + pow( 2, j ) - 1; 就是把j个汉诺塔移到一根上dp[ n - j ],然后就是普通的汉诺塔问题,即2^n - 1次移动, 然后把剩下的移动过去dp [ n - j ]. 注意pow(2, j )可能超出long long int范围.写二的次方的时候也可用移位算法. #include <iostream

BZOJ 3407: [Usaco2009 Oct]Bessie&#39;s Weight Problem 贝茜的体重问题( dp )

01背包... ----------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; i++ ) #define clr( x , c ) m

FZU Problem 2171 防守阵地 II (线段树,区间更新)

 Problem 2171 防守阵地 II Accept: 143    Submit: 565Time Limit: 3000 mSec    Memory Limit : 32768 KB  Problem Description 部队中总共有N个士兵,每个士兵有各自的能力指数Xi,在一次演练中,指挥部确定了M个需要防守的地点,指挥部将选择M个士兵依次进入指定地点进行防守任务,获得的参考指数即为M个士兵的能力之和.随着时间的推移,指挥部将下达Q个指令来替换M个进行防守的士兵们,每个参加完防守

URAL 1203 Scientific Conference(贪心 || DP)

Scientific Conference 之前一直在刷计算几何,邀请赛连计算几何的毛都买见着,暑假这一段时间就做多校,补多校的题目,刷一下一直薄弱的DP.多校如果有计算几何一定要干掉-.- 题意:给你N个报告会的开始时间跟结束时间,问你做多可以听几场报告会.要求报告会之间至少间隔为1. 思路:其实是个活动安排问题,可以用贪心也可以用DP,贪心写起来会比较简单一些,因为练习DP,所以又用DP写了一遍. 贪心的话就是一个很简单的活动选择问题,从结束时间入手,找每次的最优选择. 1 struct n

codeforces349B - Color the Fence 贪心+DP

题意:1-9每个字母需要消耗ai升油漆,问你用油漆最多刻意画多大的数字 解题思路: 首先我们要贪心,可以知道我最优是先使我们位数尽可能长,然后才是就是位数长的情况下使得从最高位开始尽可能大.所以要取满足最长位最小的那个数,方便我们DP 解题代码: 1 // File Name: 349b.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月24日 星期四 21时40分13秒 4 5 #include<vector> 6 #include&

Problem D: 勤奋的涟漪2 dp + 求导

http://www.gdutcode.sinaapp.com/problem.php?cid=1049&pid=3 dp[i][state]表示处理了前i个,然后当前状态是state的时候的最小休息天数. 比如用1代表休息,2是训练,3是运动. 如果当前这天允许的状态只是训练. 那么dp[i][3] = inf(表示不可能) 休息是无论何时都可能的了.从dp[i - 1][1--3]个状态转过来, + 1即可 那个求导是-24 #include <cstdio> #include &