URAL 1900. Brainwashing Device

来源:互联网 发布:java crm源码之家 编辑:程序博客网 时间:2024/06/06 09:47

乍看此题,还以为是扫描线+贪心,每次都扫描出最多的那个站,但是时间复杂度太高,而且写到一半的时候发现了反例. . . . . 


接下来开始推式子:


dp[ i ][ j ] = max(dp[ k1 ][ j ],dp[ k2 ][ j -1] + ans[site[ k2 ][j-1]+1][i])。

k1 ∈[j,i],k2 ∈[j-1,i].

site[ i ][ j ]表示的dp[ i ][ j ]这种情况下最右边的洗脑设备的位置.

ans[ i ][ j ]表示 以 k ∈ [ i , j ] 为始发站,经过 j 且不以 j 为终点的客人数量.


好了,理清上面的思路后问题的难点就变成了 如何统计出 ans[ ][ ]。

如果单纯的暴力枚举时间复杂度是o(n^4),二维的线段树倒是可以胜任,但是我忘了怎么写了。。。


然后学姐说可以试一试能否转化成简单的矩阵DP。


设,Map[ i ][ j ]存储的为 i 到 j 的客流量,i >= j 时,Map[ i ][ j ] = 0。

则ans[ x ][ y ] = sigma Map[ i ][ j ] ( x <= i <= y ,y < j <= n)。

接下来可以用 2*n^2 的时间将Map[ i ][ j ]处理成 (1,1) 到 ( i , j )的矩形范围内元素的和。

ans[ i ][ j ] = Map[ j ][ n ] - Map[ j ][ j ] - Map[ i-1 ][ n ] + Map[ i-1 ][ j ]。

显然这种方法预处理的时间较高,但查询只需要o(1)。缺点在于不能更新。


对于打印路径只需要在dp的时候记录一下前驱即可,不再赘述。


就这个烂题竟然卡了两天。。。。

#include <iostream>#include <algorithm>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <cmath>#include <stack>#pragma comment(linker, "/STACK:1024000000");#define EPS (1e-8)#define LL long long int#define ULL unsigned long long int#define _LL __int64#define _INF 0x3f3f3f3f#define INF 40000000#define Mod 1000000009using namespace std;int Map[501][501];struct N{    int site,data,pn,pm;}dp[501][501];int ans[501][501];bool path[510];void dfs(int n,int m){    if(n == 0 || m == 0)        return ;    if(dp[n][m].pm != m)        path[n] = true;    dfs(dp[n][m].pn,dp[n][m].pm);}int main(){    int n,m,i,j,k,t;    scanf("%d %d",&n,&m);    memset(Map,0,sizeof(Map));    for(i = 1;i < n; ++i)    {        for(j = i+1;j <= n; ++j)        {            scanf("%d",&Map[i][j]);        }    }    for(i = 1;i <= n; ++i)    {        for(j = 1;j <= n; ++j)        {            Map[i][j] += Map[i][j-1];        }    }    for(j = 1;j <= n; ++j)    {        for(i = 1;i <= n; ++i)        {            Map[i][j] += Map[i-1][j];        }    }    memset(ans,0,sizeof(ans));    for(i = 1;i <= n; ++i)    {        for(j = 1;j <= n; ++j)        {            ans[i][j] = Map[j][n] - Map[j][j] - Map[i-1][n] + Map[i-1][j];        }    }    for(i = 0;i <= n; ++i)    {        dp[i][0].data = 0;        dp[i][0].site = 0;    }    for(i = 1;i <= n; ++i)    {        for(t = min(i,m),j = 1;j <= t; ++j)        {            dp[i][j].data = dp[j-1][j-1].data + ans[dp[j-1][j-1].site+1][i];            dp[i][j].site = i;            dp[i][j].pn = j-1;            dp[i][j].pm = j-1;            for(k = j;k <= i; ++k)            {                if(dp[k][j].data > dp[k][j-1].data + ans[dp[k][j-1].site+1][i])                {                    if(dp[k][j].data > dp[i][j].data)                    {                        dp[i][j] = dp[k][j];                        dp[i][j].pn = k;                        dp[i][j].pm = j;                    }                }                else                {                    if(dp[k][j-1].data + ans[dp[k][j-1].site+1][i] > dp[i][j].data)                    {                        dp[i][j].data = dp[k][j-1].data + ans[dp[k][j-1].site+1][i];                        dp[i][j].site = i;                        dp[i][j].pn = k;                        dp[i][j].pm = j-1;                    }                }            }        }    }    memset(path,false,sizeof(path));    dfs(n-1,m);    printf("%d\n",dp[n][m].data);    for(i = 1;i <= n;++i)    {        if(path[i])        {            printf("%d",i);            break;        }    }    for(++i;i <= n;++i)    {        if(path[i])        {            printf(" %d",i);        }    }    puts("");    return 0;}




0 0
原创粉丝点击