算法 关于二元一次方程的求解
ax + by = f, a + b = h; a, b
是两个未知数,求解a, b
的值。题目保证有整数解 。
可以先求出一个未知数b
的值,可以推出b = (f - hx) / (y - x)
,在判断a + b == h ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <iostream> using namespace std;int main () { int n; cin >> n; int temp = 0x3f3f3f3f ; int ans = 0 ; while (n --) { int x; cin >> x; ans = max (ans, x - temp); temp = min (temp, x); } cout << ans << endl; return 0 ; }
贪心解法~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> #include <algorithm> #include <cstring> using namespace std;const int N = 100010 ;int n;int a[N];int f[N][2 ];int main () { cin >> n; for (int i = 1 ; i <= n; i ++) cin >> a[i]; int res = 0 ; for (int i = 2 ; i <= n; i ++) { res += max (0 , a[i] - a[i - 1 ]); } cout << res << endl; return 0 ; }
dp
解法,f[i][0],f[i][1]
分别表示第i
天不持股和持股所获得的最大利润。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <iostream> #include <cstring> #include <algorithm> using namespace std;const int N = 100010 ;int f[N][2 ];int pr[N];int main () { int n; cin >> n; for (int i = 1 ; i <= n; i ++) cin >> pr[i]; f[1 ][1 ] = -pr[1 ]; for (int i = 2 ; i <= n; i ++) { f[i][0 ] = max (f[i - 1 ][0 ], f[i - 1 ][1 ] + pr[i]); f[i][1 ] = max (f[i - 1 ][0 ] - pr[i], f[i - 1 ][1 ]); } cout << max (f[n][0 ], f[n][1 ]) << endl; return 0 ; }
max()函数比较多个数的大小
int maxn = max({a, b, c, d});
注意a, b, c, d
是同一个类型
前后缀分解~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <iostream> #include <cstring> #include <algorithm> using namespace std;const int N = 100010 ;int p[N];int dp1[N], dp2[N];int n;int main () { cin >> n; for (int i = 1 ; i <= n; i++) cin >> p[i]; int t = 1e5 ; for (int i = 1 ; i <= n; i ++) { dp1[i] = max (dp1[i - 1 ], p[i] - t); t = min (t, p[i]); } t = -1 ; for (int i = n; i >= 1 ; i --) { t = max (t, p[i]); dp2[i] = ma' x (dp2[i + 1 ], t - p[i]); } int res = 0 ; for (int i = 1 ; i <= n; i ++) res = max (res, dp1[i] + dp2[i]); cout << res << endl; return 0 ; }
状态转移方程的初始化,非入口初始化为负无穷,入口按题目要求初始化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream> #include <cstring> #include <algorithm> using namespace std;const int N = 100010 , M = 110 ;int n, k;int a[N];int f[N][M][2 ];int main () { cin >> n >> k; for (int i = 1 ; i <= n; i ++) cin >> a[i]; memset (f,0xcf ,sizeof f); for (int i = 1 ; i <= n; i ++) { f[i][0 ][1 ] = max (f[i - 1 ][0 ][1 ], -a[i]); f[i][0 ][0 ] = 0 ; } for (int i = 1 ; i <= n; i ++) for (int j = 1 ; j <= k; j ++) { f[i][j][0 ] = max (f[i - 1 ][j - 1 ][1 ] + a[i], f[i - 1 ][j][0 ]); f[i][j][1 ] = max (f[i - 1 ][j][1 ], f[i - 1 ][j][0 ] - a[i]); } int ans = 0 ; for (int i = 1 ; i <= k; i ++) ans = max (ans, f[n][i][0 ]); cout << ans << endl; return 0 ; }
有个一天的“冷静期”,即卖出要过一天才能买,不限次数,其余和股票IV 一样。
f[i][0]
表示的是第i
天未持有股票,f[i][1]
表示的是第i
天持有股票,f[i][2]
表示的是第i
天刚买完,第i+1
天处于“冷静期”,不能买股票。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <iostream> #include <cstring> using namespace std;const int N = 1e5 + 10 ;int n;int w[N];int f[N][3 ];int main () { cin >> n; for (int i = 1 ; i <= n; ++ i) cin >> w[i]; memset (f, -0x3f , sizeof f); f[0 ][0 ] = 0 ; for (int i = 1 ; i <= n; ++ i) { f[i][0 ] = max (f[i - 1 ][0 ], f[i - 1 ][2 ]); f[i][1 ] = max (f[i - 1 ][1 ], f[i - 1 ][0 ] - w[i]); f[i][2 ] = f[i - 1 ][1 ] + w[i]; } cout << max (f[n][0 ], f[n][2 ]) << endl; return 0 ; }
和股票买卖II类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> using namespace std;const int N = 100010 ;int a[N];int f[N][2 ];int n, m;int main () { cin >> n >> m; for (int i = 1 ; i <= n; i ++) cin >> a[i]; f[0 ][1 ] = -1e5 ; for (int i = 1 ; i <= n; i ++) { f[i][0 ] = max (f[i - 1 ][0 ], f[i - 1 ][1 ] + a[i] - m); f[i][1 ] = max (f[i - 1 ][0 ] - a[i], f[i - 1 ][1 ]); } cout << f[n][0 ] << endl; return 0 ; }
枚举前一个序列有多少个,枚举到字符串得最后一个字符再加上这个个数~