• 【简●解】[SDOI2008] Sue的小球


    计划着刷(DP)题结果碰到了这样一道论文题,幸好不是太难


    【题目大意】

    口水话有点多,所以就直接放链接。传送门

    【分析】

    看到题首先联想到了曾经做过的关路灯。所以先按(x)值排序,然后进行区间(DP)

    不妨设(f_1[i][j])(f_2[i][j])分别表示从起点出发已射落(i)(j)这一段彩蛋,当前停留在(i)点,(j)点的最大得分(v)

    考虑 (f_1[i][j]),即点(i)是当前射击的彩蛋,射击的得分与当前时刻挂钩,但 是当前的时刻是不能从(f_1[i][j])的状态中表示出来的,我们进一步考虑 (f_1[i][j])的求解。

    由于射击(i)的得分是(y_i−t∗v_i),而(t)等于之前每一步决策移动的时间总和,这样我们就可以把(t∗v_i)​在之前的移动中就计算,也就是说每次移动都要把未来会减少的得分计算在内。 比如说从(f_1[i+1][j])推到(f_1[i][j]),即从(i+1)走到(i)时除了(i+1)(j)这一段彩蛋外,其它的彩蛋都在下落,将这丢失的分数一并计算到从(i+1)走到(i)中。由于(-t*v_i)已经在之前决策时计算,所以射击时直接加上(y_i)即可。

    所以可以先用(sum[])计算(v_i)的前缀和,然后(DP)方程:

    [f_1[i][j]=y[i]+max(f_1[i+1][j]+Sum(i+1,j)*(x_{i+1}-x_i),f_2[i+1][j]+Sum(i+1,j)*(x_j-x_i) ]

    [f_2[i][j]=y[i]+max(f_1[i][j-1]+Sum(i,j-1)*(x_{j}-x_{i}),f_2[i][j-1]+Sum(i,j-1)*(x_j-x_{j-1}) ]

    然后(O(n^2))过。

    【Code】

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int MAX = 1000 + 5; 
    const int INF = 0x3f3f3f3f;
    inline int read(){
    	int f = 1, x = 0;char ch;
    	do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');
    	do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
    	return f*x;
    }
    int n, bj;
    double x0, f[3][MAX][MAX], sum[MAX];
    struct sakura { double x, y, v; }sak[MAX];
    inline bool cmp(sakura a, sakura b) { return a.x < b.x; }
    inline double Sum(int l, int r) { return sum[n] - sum[r] + sum[l - 1]; }
    inline double ab(double a) { return a < 0 ? -a : a; }
    int main(){
    	n = read(); ++n, x0 = read(); 
    	sak[1].x = x0, sak[1].y = sak[1].v = 0;
    	for (int i = 2;i <= n; ++i) {
    		sak[i].x = read();
    	}
    	for (int  i = 2;i <= n; ++i) {
    		sak[i].y = read();
    	}
    	for (int i = 2;i <= n; ++i) {
    		sak[i].v = read(); 
    	}
    	sort(sak + 1, sak + 1 + n, cmp);
    	for (int i = 1;i <= n; ++i) {
    		sum[i] = sum[i - 1] + sak[i].v;
    		if (ab(sak[i].x - x0) <= 1e-10 && ab(sak[i].y) <= 1e-10) {
    			bj = i;
    		}
    	}
    	memset(f, -INF, sizeof (f));
    	f[1][bj][bj] = f[2][bj][bj] = 0.0;
    	for (int k = 1;k <= n; ++k) {
    		for (int i = 1;i + k <= n; ++i) {
    			int j = i + k;
    			f[1][i][j] = sak[i].y + max(f[1][i + 1][j] - (sak[i + 1].x - sak[i].x) * Sum(i + 1, j), f[2][i + 1][j] - (sak[j].x - sak[i].x) * Sum(i + 1, j));
    			f[2][i][j] = sak[j].y + max(f[1][i][j - 1] - (sak[j].x - sak[i].x) * Sum(i, j - 1), f[2][i][j -1] - (sak[j].x - sak[j - 1].x) * Sum(i, j - 1)); 
    		}
    	}
    	printf("%.3lf", max(f[1][1][n], f[2][1][n]) / 1000.0);
    	return 0;
    }
    

    后来听人说这是未来(DP)???

  • 相关阅读:
    Cornerstone-忽略(隐藏)文件
    ios开发xcode8+ 无需开发者账号,app打包ipa
    ssh-ajax登陆action返回字符串
    手动编译包含两个import自写类的java类。
    关闭IO资源
    java聊天室二(客户端)
    java聊天室一(服务器)
    文件IO常用操作
    Hive启动时的棘手问题的处理
    对于java反射的理解
  • 原文地址:https://www.cnblogs.com/silentEAG/p/10935723.html
Copyright © 2020-2023  润新知