石子合并

来源:互联网 发布:js文件怎么运行程序 编辑:程序博客网 时间:2024/04/29 18:56

这是一道经典的动态规划问题。设f[i][j]表示合并第i个到第j个石子所得的最小得分,f[i][j] = min{f[i][j], f[i][k - 1] + f[k][j] + sum[j] - sum[i - 1]} (i < k <= j),时间复杂度是O(n3).

这道题可用平行四边形优化到O(n2),不过这个优化虽然会照着写,但还不太明白……

http://acm.nankai.edu.cn/p1137.html

这道题注意是圆形,否则会WA的,数据范围小,不需要优化

///http://acm.nankai.edu.cn/p1137.html#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define LL long longconst LL INF = (LL)1<<60;LL sum[210], f[210][210], d[210][210], num[210];int main(){    //freopen("input.txt", "r", stdin);    int n;    LL ans1, ans2;    while(cin >> n){        sum[0] = 0;        for(int i = 1; i <= n; i++){            cin>>num[i];            sum[i] = sum[i - 1] + num[i];        }        for(int i = 1; i < n; i++){            num[i + n] = num[i];            sum[i + n] = sum[i + n - 1] + num[i + n];        }        memset(f, 0, sizeof(f));        memset(d, 0, sizeof(d));        for(int l = 2; l <= n; l++){            for(int i = 1, j; i + l - 1 < 2 * n; i++){                j = i + l - 1;                f[i][j] = INF;                for(int k = i; k < j; k++){                    f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + sum[j] - sum[i - 1]);                    d[i][j] = max(d[i][j], d[i][k] + d[k + 1][j] + sum[j] - sum[i - 1]);                }            }        }        ans1 = INF;        ans2 = 0;        for(int i = 1; i <= n; i++){            ans1 = min(ans1, f[i][i + n - 1]);            ans2 = max(ans2, d[i][i + n - 1]);        }        cout<<ans1<<endl<<ans2<<endl;    }    return 0;}
http://coder.buct.edu.cn/oj/Problem.aspx?pid=1725
用到了平行四边形优化

//四边形优化 http://coder.buct.edu.cn/oj/Problem.aspx?pid=1725#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define LL long longconst LL INF = (LL)1<<60;const int MAXN = 1010;LL sum[MAXN], f[MAXN][MAXN], prt[MAXN][MAXN], num[MAXN];int main(){    //freopen("input.txt", "r", stdin);    int n;    while(cin >> n){        sum[0] = 0;        for(int i = 1; i <= n; i++){            cin>>num[i];            sum[i] = sum[i - 1] + num[i];        }        memset(f, 0, sizeof(f));        memset(prt, 0, sizeof(prt));        for(int i = 1; i <= n; i++) prt[i][i] = i;        for(int l = 2; l <= n; l++){            for(int i = 1, j; i <= n - l + 1; i++){                j = i + l - 1;                f[i][j] = INF;                for(int k = prt[i][j - 1]; k <= prt[i + 1][j]; k++){                    if(f[i][j] > f[i][k - 1] + f[k][j]){                        f[i][j] = f[i][k - 1] + f[k][j];                        prt[i][j] = k;                    }                }                f[i][j] += sum[j] - sum[i - 1];            }        }        cout<<f[1][n]<<endl;    }    return 0;}


原创粉丝点击