首页 > 代码库 > UVALive 4731 dp+贪心
UVALive 4731 dp+贪心
这个题首先要利用题目的特性,先贪心,否则无法进行DP
因为求期望的话,越后面的乘的越大,所以为了得到最小值,应该把概率值降序排序,把大的数跟小的系数相乘
然后这种dp的特性就是转移的时候,由 i推到i+1每次添加一个数,就要考虑这个新数应该和谁放在一组,枚举他放在哪一组即可
dp[i][j]代表当前第i个数有j个分组时候的最小值
dp[i][j]=dp[k][j-1]+i(prefix[i]-prefix[k-1]),k代表枚举第几个数开始和当前新添加的数为一组,prefix为前缀和,为了迅速得出区间和
注意边界处理和一些细节
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <set>#define LL __int64using namespace std;struct node{ int x,y; bool operator < (const node&rhs) const { if (x==rhs.x) return y<rhs.y; return x<rhs.x; }}tasks[100010];bool cmp(node a,node b){ if (a.x==b.x) return a.y<b.y; return a.x<b.x;}int n,m;multiset<node> v;multiset<node>::iterator it;/*int bs(int p,int q){ int L=0,R=v[p].size(),mid; while (L<R) { mid=(L+R)>>1; if (v[p][mid]<tasks[q].x) L=mid+1; else R=mid; } return L;}*/int main(){ int a,b; while (scanf("%d%d",&m,&n)!=EOF) { int maxn=0; v.clear(); for (int i=1;i<=m;i++){ scanf("%d%d",&a,&b); v.insert((node){a,b}); maxn=max(b,maxn); } for (int i=1;i<=n;i++){ scanf("%d%d",&a,&b); tasks[i].x=a; tasks[i].y=b; } sort(tasks+1,tasks+1+n); //for (int i=0;i<=maxn;i++) sort(v[i].begin(),v[i].end()); LL ans=0; int sum=0; for (int i=n;i>=1;i--){ it=v.lower_bound(tasks[i]); if (it==v.end()) continue; else{ v.erase(it); ans+=(LL)tasks[i].x*500+(LL)tasks[i].y*2; sum++; } } printf("%d %I64d\n",sum,ans); } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。