hdu 4362 Dragon Ball(dp)

来源:互联网 发布:wind 淘宝 编辑:程序博客网 时间:2024/05/18 01:59

http://acm.hdu.edu.cn/showproblem.php?pid=4362

题意:有m个阶段,每个阶段都有n个龙珠,当在某一阶段选择一个龙珠,该阶段其他龙珠都会消失。给出两个m*n的矩阵,第一个矩阵表示消灭第i个阶段第j个龙珠的位置,第二个矩阵表示取第i个阶段第j个龙珠消耗的能量,同时当第x个位置到第个位置需要消耗 | y - x|的能量。问最后每个阶段取走一个龙珠最小的能量消耗。


思路:状态转移方程很容易,dp[i][j] = min(dp[i-1][k] + abs( pos[i-1][k] - pos[i][j] ) ) + energy[i][j]。

但由于n较大,想着会TLE。试着敲出来,果真TLE。改了改细节,然后加了个内联函数水过。

#include <stdio.h>#include <string.h>#include <algorithm>#include <cmath>using namespace std;const int INF = 0x3f3f3f3f;int n,m,x;int pos[55][1010],ener[55][1010],dp[55][1010];inline int chk(int x){    if(x < 0)        return -x;    return x;}int main(){    int test;    scanf("%d",&test);    while(test--)    {        scanf("%d %d %d",&n,&m,&x);        for(int i = 0; i < n; i++)        {            for(int j = 0; j < m; j++)                scanf("%d",&pos[i][j]);        }        for(int i = 0; i < n; i++)        {            for(int j = 0; j < m; j++)                scanf("%d",&ener[i][j]);        }        for(int j = 0; j < m; j++)            dp[0][j] = chk(pos[0][j]-x) + ener[0][j];        for(int i = 1; i < n; i++)        {            for(int j = 0; j < m; j++)            {                int tmp = INF;                for(int k = 0; k < m; k++)                {                    int sum = dp[i-1][k] + chk(pos[i-1][k] - pos[i][j]);                    if(tmp > sum)                        tmp = sum;                }                dp[i][j] = tmp+ener[i][j];            }        }        int ans = INF;        for(int j = 0; j < m; j++)            ans = min(ans, dp[n-1][j]);        printf("%d\n",ans);    }        return 0;}

再看状态转移方程,dp[i][j] = min(dp[i-1][k] + abs( pos[i-1][k] - pos[i][j] ) ) + energy[i][j],发现dp[i][j]与energy[i][j] 和 pos[i][j]无关,去绝对值的方法是排序,对pos排序后,用单调队列存上一行 dp[i-1][k] +(-) pos[i-1][k]的值,最后取队首(最大)即可。该题的正解应该是单调队列,做了hdu437后,又回来A一下。

#include <stdio.h>#include <string.h>#include <algorithm>#include <cmath>using namespace std;const int INF = 0x3f3f3f3f;struct node{    int pos;    int ener;    bool operator < (const struct node &tmp)const    {        return pos < tmp.pos;    }}point[55][1010];int dp[55][1010];int abss(int x){    if(x < 0)        return -x;    return x;}int n,m,x;int main(){    int test;    scanf("%d",&test);    while(test--)    {        scanf("%d %d %d",&n,&m,&x);        for(int i = 1; i <= n; i++)            for(int j = 1; j <= m; j++)                scanf("%d",&point[i][j].pos);        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= m; j++)                scanf("%d",&point[i][j].ener);            sort(point[i]+1,point[i]+1+m);        }        memset(dp,INF,sizeof(dp));        for(int j = 1; j <= m; j++)            dp[1][j] = abss(point[1][j].pos - x) + point[1][j].ener;        for(int i = 2; i <= n; i++)        {            int minn = INF;            int index = 1;            for(int j = 1; j <= m; j++)            {                while(index <= m && point[i-1][index].pos <= point[i][j].pos)                {                    minn = min(minn, dp[i-1][index]-point[i-1][index].pos);                    index++;                }                dp[i][j] = minn + point[i][j].pos;            }            minn = INF;            index = m;            for(int j = m; j >= 1; j--)            {                while(index >= 1 && point[i-1][index].pos > point[i][j].pos)                {                    minn = min(minn,dp[i-1][index] + point[i-1][index].pos);                    index--;                }                dp[i][j] = min(dp[i][j], minn-point[i][j].pos);                dp[i][j] += point[i][j].ener;             }        }        int ans = dp[n][1];        for(int i = 2; i <= m; i++)            ans = min(ans, dp[n][i]);        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击