校内欢乐赛之爆零季 T2

本文深入探讨了使用费用流和神DP解决特定问题的方法,详细解释了费用流的基本思想及其应用,同时展示了如何通过巧妙的DP状态转移实现优化。文中还通过实例分析了如何将问题转化为网络流问题,并利用DP技术高效求解。

题目:这里写图片描述
思路:费用流吧,,欢快水掉,,不过貌似还有一种神建图?还有一种神dp?都不太会啊,,
很幸运的搞明白了两种神奇的做法,,,
费用流:看成三个块,,,可以看出每个块内至多有k个对吧,,
可以把一种合法解分解为不超过k条不相交路径,,路径端点满足相差至少为n,,,为什么这么想呢?不知道啊,,貌似是大神在搞k = 1时想出来的,,确实k = 1比较好想,,然而怎么证明?反证法好了,,对应啊,,网络流对应一定是合法解,,因为假设不合法,,那么某个n里有多于k个那一定是多于k条路而这不可能啊,,
合法解对应网络流,,,这里i个合法解向第i+k个连,,,对应网络流,,神啊!orz TA orz 韩宵月 orz faebdc
dp:一看啊k好小啊,,可以暴力枚举三个块内选的个数,,(准确的说前两个就可以了)
f d,i,j,k表示,在3个块内前d个,各自已经选了i,j,k个,,然后块内枚举保证了合法,,跨块之间可以判断一下,,,然后由合法的i,j,k转移过来即可啊,,边界非常多,,共8种情况,,,我也是醉了啊,,,我dp真是弱爆了!!!
faebdc 神dp代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 605;
const int M = 11;
int n,m;
int xu[N][3];
int dp[M][M][M];
int ans=-987654321;
int main()
{
    freopen("war.in","r",stdin);
    freopen("war.out","w",stdout);
    int i,j,k,d;
    int s,t;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        scanf("%d",&xu[i][0]);
    for(i=1;i<=n;i++)
        scanf("%d",&xu[i][1]);
    for(i=1;i<=n;i++)
        scanf("%d",&xu[i][2]);
    for(s=0;s<=m;s++)
    {
        for(t=0;t<=m;t++)
        {
            memset(dp,0xc0,sizeof dp);
            dp[0][0][0]=0;
            for(d=1;d<=n;d++)
            {
                for(i=s;i>=0;i--)
                {
                    for(j=t;j>=0;j--)
                    {
                        if(j+s-i>m)
                            continue;
                        for(k=m;k>=0;k--)
                        {
                            if(k+t-j>m)
                                continue;
                            int now=0;
                            if(i)
                            {
                                now+=xu[d][0];
                                if(j)
                                {
                                    now+=xu[d][1];
                                    if(k)
                                    {
                                        now+=xu[d][2];
                                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k-1]+now);
                                        now-=xu[d][2];
                                    }
                                    if(k+t-j<m)
                                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+now);
                                    now-=xu[d][1];
                                }
                                if(j+s-i<m)
                                {
                                    if(k)
                                    {
                                        now+=xu[d][2];
                                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]+now);
                                        now-=xu[d][2];
                                    }
                                    dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k]+now);
                                }
                                now-=xu[d][0];
                            }
                            if(j)
                            {
                                now+=xu[d][1];
                                if(k)
                                {
                                    now+=xu[d][2];
                                    dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k-1]+now);
                                    now-=xu[d][2];
                                }
                                if(k+t-j<m)
                                    dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k]+now);
                                now-=xu[d][1];
                            }
                            if(k)
                            {
                                now+=xu[d][2];
                                dp[i][j][k]=max(dp[i][j][k],dp[i][j][k-1]+now);
                                now-=xu[d][2];
                            }
                        }
                    }
                }
            }
            for(i=0;i<=m;i++)
                ans=max(ans,dp[s][t][i]);
        }
    }
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值