1. 程式人生 > >數字遊戲II

數字遊戲II

fin con while efi tchar names 圖片 嘟嘟 ==

題面好難找:嘟嘟嘟

貪心 + dp。

首先要按bi的降序排序,讓每一次減少大的數盡量靠前。為啥咧?於是我們就需要證明:令sum = a1 - (1 - 1) * b1 + a2 - (2 - 1) * b2 + a3 - (3 - 1) * b3 + ……+ an - (n - 1) * bn,整理得:sum = (a1 + a2 + a3 + ……+ an) + (0 * b1 + 1 * b2 + 2 * b3 + ……+ (n - 1) * bn)。因為Σan是定值,所以讓sum最大就是讓bi降序排序。

然後dp。

令dp[i][j]第 j 回合取ai的最大得分,仿照01背包:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + a[i] - (j - 1) * b[i])。

於是這道題就做完啦。

技術分享圖片
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 13 #define space putchar(‘ ‘) 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 205; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last =
; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - 0; ch = getchar();} 27 if(last == -) ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar(-); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + 0); 35 } 36 37 int n, m; 38 struct Node 39 { 40 int a, b; 41 bool operator < (const Node &oth)const 42 { 43 return b > oth.b; 44 } 45 }t[maxn]; 46 ll dp[maxn][maxn]; 47 48 int main() 49 { 50 n = read(); m = read(); 51 for(int i = 1; i <= n; ++i) t[i].a = read(); 52 for(int i = 1; i <= n; ++i) t[i].b = read(); 53 sort(t + 1, t + n + 1); 54 for(int i = 1; i <= n; ++i) 55 for(int j = 1; j <= m; ++j) 56 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + t[i].a - (j - 1) * t[i].b); 57 write(dp[n][m]), enter; 58 return 0; 59 }
View Code

數字遊戲II