斜率dp的几题.
hdu2829
//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
#define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)
typedef long long LL;
typedef vector <int> VI;
const int INF = 1000000000;
const double eps = 1e-10;
const int MAXN = 1005;
int n, m;
int s[MAXN];
int a[MAXN];
int tol;
int q[MAXN], be, ed;
int dp[MAXN][MAXN];
int getUp(int i, int j, int k)
{
// return -1 * dp[k - 1][j] + s[j] * s[j] - (-1 * dp[k - 1][i] + s[i] * s[i]);
return s[j] * s[j] - dp[k - 1][j] - (s[i] * s[i] - dp[k - 1][i]);
}
int getDown(int i, int j)
{
return s[j] - s[i];
}
void solve()
{
FE(i, 1, m)
{
be = 1;
ed = 0;
q[++ed] = i;
FE(j, i + 1, n)
{
while (be < ed)
{
int p1= q[be];
int p2 = q[be + 1];
int x1 = getDown(p1, p2);
int y1 = getUp(p1, p2, i);
if (y1 <= s[j] * x1) be++;
else break;
}
int p = q[be];
dp[i][j] = dp[i - 1][p] + s[p] * (s[j] - s[p]);
while(be < ed)
{
int p1 = q[ed - 1];
int p2 = q[ed];
int x1 = getDown(p1, p2);
int x2 = getDown(p2, j);
int y1 = getUp(p1, p2, i);
int y2 = getUp(p2, j, i);
if (y1 * x2 >= y2 * x1) ed--;
else break;
}
q[++ed] = j;
}
}
printf("%d\n", tol - dp[m][n]);
}
int main ()
{
while (~RII(n, m) && (n || m))
{
s[0] = 0;
FE(i, 1, n)
{
RI(a[i]);
s[i] = s[i - 1] + a[i];
}
tol = 0;
FED(i, n, 2)
{
tol += a[i] * s[i - 1];
}
CLR(dp, 0);
solve();
}
return 0;
}
hdu3045
//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
#define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)
typedef long long LL;
typedef vector <int> VI;
const int INF = 1000000000;
const double eps = 1e-10;
const int MAXN = 400005;
int q[MAXN];
LL dp[MAXN];
LL a[MAXN], s[MAXN];
int be, ed;
int n, k;
LL getUp(int i, int j)
{
return dp[j] - s[j] + j * a[j + 1] - (dp[i] - s[i] + i * a[i + 1]);
}
LL getDown(int i, int j)
{
return a[j + 1] - a[i + 1];
}
void solve()
{
CLR(dp, 0);///
be = 1;
ed = 0;
q[++ed] = 0;
FE(i, k, n)///
{
while (be < ed)
{
int p1 = q[be];
int p2 = q[be + 1];
LL x1 = getDown(p1, p2);
LL y1 = getUp(p1, p2);
if (y1 <= i * x1) be++;
else break;
}
int p = q[be];
dp[i] = dp[p] + s[i] - s[p] - (i - p) * a[p + 1];
int j = i - k + 1;
if (j < k) continue;///!!!!!!!!!!!!!!!!!!!!!!!!!
while (be < ed)
{
int p1 = q[ed - 1];
int p2 = q[ed];
LL x1 = getDown(p1, p2);
LL x2 = getDown(p2, j);
LL y1 = getUp(p1, p2);
LL y2 = getUp(p2, j);
if (y1 * x2 >= y2 * x1) ed--;
else break;
}
q[++ed] = j;
}
printf("%I64d\n", dp[n]);
}
int main ()
{
while (~RII(n, k))
{
FE(i, 1, n) scanf("%I64d", &a[i]);
sort(a + 1, a + 1 + n);
s[0] = 0;
FE(i, 1, n) s[i] = s[i - 1] + a[i];
solve();
}
return 0;
}
hdu3480
//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
#define CPY(a, b) memcpy(a, b, sizeof(a))
#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
//STL
#define SZ(V) (int)V.size()
#define PB push_back
#define EQ(a, b) (fabs((a) - (b)) <= 1e-10)
#define ALL(c) (c).begin(), (c).end()
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
#define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const int INF = 1000000000;
const double eps = 1e-10;
const int MAXN = 10005;
int q[MAXN], be, ed;
int a[MAXN];
int dp[5005][MAXN];
int n, m;
int getUp(int i, int j, int k)
{
return dp[k - 1][j] - dp[k - 1][i] + a[j + 1] * a[j + 1] - a[i + 1] * a[i + 1];
}
int getDown(int i, int j)
{
return a[j + 1] - a[i + 1];
}
int solve()
{
FE(i, 1, n)
dp[1][i] = (a[i] - a[1]) * (a[i] - a[1]);
FE(i, 2, m)
{
be = 1;
ed = 0;
q[++ed] = i - 1;
FE(j, i, n)
{
while (be < ed)
{
int p1 = q[be];
int p2 = q[be + 1];
int x1 = getDown(p1, p2);
int y1 = getUp(p1, p2, i);
if (y1 <= 2 * a[j] * x1) be++;
else break;
}
int p = q[be];
dp[i][j] = dp[i - 1][p] + (a[j] - a[p + 1]) * (a[j] - a[p + 1]);
while (be < ed)
{
int p1 = q[ed - 1];
int p2 = q[ed];
int p3 = j;
int x1 = getDown(p1, p2);
int x2 = getDown(p2, p3);
int y1 = getUp(p1, p2, i);
int y2 = getUp(p2, p3, i);
if (x1 * y2 <= x2 * y1) ed--;
else break;
}
q[++ed] = j;
}
}
printf("%d\n", dp[m][n]);
}
int main ()
{
int T;
RI(T);
int iCase = 1;
while (T--)
{
RII(n, m);
// a[0] = 0;
FE(i, 1, n)
RI(a[i]);
sort(a + 1, a + 1 + n);
// CLR(dp, 0);
printf("Case %d: ",iCase++);
solve();
}
return 0;
}
斜率优化DP算法解析
本文介绍了斜率优化动态规划算法的应用案例,包括hdu2829、hdu3045和hdu3480三道题目。通过这些实例展示了如何使用斜率优化技巧来提高动态规划算法效率,特别关注于如何利用单调队列进行优化。
1151

被折叠的 条评论
为什么被折叠?



