标签:sort local ring str def string oca 就是 time
https://codeforces.com/gym/100340/problem/A
老人给n个小学生发m个饼干,每人最少一个,最后都发完了。这些小学生每个人都有一个贪心值g,如果有x个人的饼干比他多,那么他的不高兴指数就是$gx$
给出n,m,所有贪心值,输出不高兴指数的和的最小值,同时输出如何发饼干才能使小学生的不高兴指数的和最小。
首先贪心,如果有两个小学生的贪心值分别为$a$和$b$,发的饼干分别为$c$和$d$,若$a<b,c<d$,那么$ac+bd>ad+bc$($a(c-d)-b(c-d)=(a-b)(c-d)>0$),所以贪心值大的就需要多发
将贪心值排序后,从左往右发的饼干递减,那么就相当于一层一层搭上去的。
就可以写转移了
$dp[i][j]$表示前$i$个人发$j$块饼干
就有两种转移
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<map> #include<cassert> #define REP(i,a,b) for(register int i=(a); i<(b); i++) #define REPE(i,a,b) for(register int i=(a); i<=(b); i++) #define PERE(i,a,b) for(register int i=(a); i>=(b); i--) using namespace std; typedef long long ll; int n,m; struct node { int a,id; bool operator<(const node &r) const { return a>r.a; } } g[37]; int s[37]; int dp[37][5007], pi[37][5007], pj[37][5007]; int ans[37]; inline void prn(int i, int j) { if(i==-1) return; REPE(x,1,i) ans[g[x].id]++; prn(pi[i][j], pj[i][j]); } int main() { #ifndef LOCAL freopen("cookies.in", "r", stdin); freopen("cookies.out", "w", stdout); #endif memset(ans,0,sizeof ans); scanf("%d%d", &n, &m); REPE(i,1,n) scanf("%d", &g[i].a), g[i].id=i-1; sort(g+1,g+n+1); s[0]=0; REPE(i,1,n) s[i]=s[i-1]+g[i].a; memset(dp,0x3f,sizeof(dp)); dp[0][0]=0, pi[0][0]=-1, pj[0][0]=-1; REPE(i,1,n) REPE(j,i,m) { dp[i][j] = dp[i][j-i], pi[i][j]=i, pj[i][j]=j-i; REP(k,0,i) { int nd = dp[k][j-i] + k*(s[i]-s[k]); if(nd<dp[i][j]) { dp[i][j]=nd, pi[i][j]=k, pj[i][j]=j-i; } } } printf("%d\n", dp[n][m]); prn(n, m); REP(i,0,n) { if(i) putchar(‘ ‘); printf("%d", ans[i]); } }
标签:sort local ring str def string oca 就是 time
原文地址:https://www.cnblogs.com/sahdsg/p/12416466.html