hdu 2686 Matrix - 最小费用最大流 或 多线程DP

/*

hdu 2686 Matrix

方阵(每个格子里面都有一个数字)里面从左上走到右下,再回来,一个点只能走一次,求数字之和最大是多少

相当与从左上到右下选两条不交叉的路,使和最大

典型的最大费用最大榴



我要说的是,这是昨天的省赛的原题,当时就像到了什最大费用最大流,但是当时脑袋一热,又感觉不是(韩式我对这个算法的理解不够啊)

其实只要在那个模板(http://blog.csdn.net/qq172108805/article/details/7857503)的基础上该一行就可以了(T﹏T)

*/

#include<stdio.h>

#include<string.h>

#include<queue>

using namespace std;

struct node

{

	int u,v,f,c,next;

}e[100000];

int n,k,head[5010],yong,s,t,maxflow;

int map[55][55];

int pre[5010],dist[5010],vis[5010];

void adde(int u,int v,int c,int f)//加边

{

	e[yong].u=u,e[yong].v=v,e[yong].c=c,e[yong].f=f;

	e[yong].next=head[u],head[u]=yong++;



	e[yong].u=v,e[yong].v=u,e[yong].c=-c,e[yong].f=0;//这是它的退边

	e[yong].next=head[v],head[v]=yong++;

}

int spfa()//spfa求最短路

{

	int i,u,v;

	for(i=0;i<=t;i++)

		pre[i]=-1,vis[i]=0,dist[i]=0x7fffffff;

	dist[s]=0;

	vis[s]=1;

	queue<int>q;

	q.push(s);

	while(!q.empty())

	{

		u=q.front();

		q.pop();

		for(i=head[u];i!=-1;i=e[i].next)

		{

			v=e[i].v;

			if(e[i].f>0&&dist[u]+e[i].c<dist[v])

			{

				dist[v]=dist[u]+e[i].c;

				pre[v]=i;//标记的是走到这儿的那条边

				if(!vis[v])

				{

					vis[v]=1;

					q.push(v);

				}

			}

		}

		vis[u]=0;

	}

	if(dist[t]==0x7fffffff)

		return 0;

	return 1;

}

int min(int a,int b){return a<b?a:b;}

void add()//加流  修改残留网络

{

	int v;

	int mm=0x7fffffff;

	for(v=pre[t];e[v].u!=s;v=pre[e[v].u])//求最小的 可增流

		mm=min(mm,e[v].f);

	for(v=pre[t];e[v].u!=s;v=pre[e[v].u])

	{

		e[v].f-=mm;//修改残留网络

		e[v^1].f+=mm;

		maxflow+=mm*e[v].c;//加到费用里边

	}

}

int main()

{

	int i,j,b;

	while(scanf("%d",&n)!=EOF)

	{

	    k=2;//其实我就只是该了这里!!!其余的跟我的模板一模一样 http://blog.csdn.net/qq172108805/article/details/7857503

		maxflow=0;//初始化

		s=n*n*2;

		t=s+1;

		yong=0;

		memset(head,-1,sizeof(head));

		for(i=1;i<=n;i++)//读数据

			for(j=1;j<=n;++j)

				scanf("%d",&map[i][j]);



		for(i=1;i<=n;i++)//拆点建边

			for(j=1;j<=n;++j)

			{

				b=(i-1)*n+j-1;//点的编号是0~n*n-1

				adde(b*2,b*2+1,-map[i][j],1);//

				adde(b*2,b*2+1,0,k-1);

			}

		for(i=1;i<=n;i++)//向右建边

			for(j=1;j<n;j++)

			{

				b=(i-1)*n+j-1;

				adde(b*2+1,2*(b+1),0,k);

			}

		for(i=1;i<n;++i)//向下建边

			for(j=1;j<=n;++j)

			{

				b=(i-1)*n+j-1;

				adde(b*2+1,2*(b+n),0,k);

			}

		adde(s,0,0,k);//头

		adde(n*n*2-1,t,0,k);//尾



		while(spfa())

			add();



		printf("%d\n",-maxflow);//再取相反数

	}

	return 0;

}

下面的是用双线程DP做的

 

/*

还是上面那个题,用双线程dp做的



让两个进程同时进行,枚举步数K,当x1==x2||y1==y2时跳过,得状态转移方程:

dp(k,x1,y1,x2,y2)=max(dp(k-1,x1-1,y1,x2-1,y2), dp(k-1,x1-1,y1,x2,y2-1),dp(k-1,x1,y1-1,x2-1,y2),dp(k-1,x1,y1-1,x2,y2-1))+data(x1,y1)+data(x2,y2);

dp(k-1,x1-1,y1,x2-1,y2)第一条路来自上面,第二条路来自上面

dp(k-1,x1-1,y1,x2,y2-1)第一条路来自上面,第二条路来自左面

dp(k-1,x1,y1-1,x2-1,y2)第一条路来自左面,第二条路来自上面

dp(k-1,x1,y1-1,x2,y2-1)第一条路来自左面,第二条路来自左面

由于只能走右或下,所以坐标满足x+y=k。这样就能降低维数为3维(y1=k-x1,y2=k-x2),方程:

dp(k,x1,x2)=max(dp(k-1,x1,x2),dp(k-1,x1-1,x2),dp(k-1,x1,x2-1),dp(k-1,x1-1,x2-1))+data(x1,k-x1)+data(x2,k-x2);



但是我的数组开成

int maps[55][55];

int dp[100][55][55];

(55*55+100*55*55)*4=1193k<32768K为什么老是返回WA





某个博客上说的好,DP问题,增加限制就意味着增加维度

*/

#include<stdio.h>

#include<string.h>

#include<algorithm>

using namespace std;

int maps[40][40];

int dp[80][40][40];

int n;

int Max(int a,int b,int c,int d)

{

    return max(a,max(b,max(c,d)));

}

int main()

{

    int i,j,k;

    while(scanf("%d",&n)!=EOF)

    {

        for(i=0; i<n; ++i)

        {

            for(j=0; j<n; ++j)

            {

                scanf("%d",&maps[i][j]);

            }

        }

        memset(dp,0,sizeof(dp));

        for(k=1; k<2*n-2; ++k)

        {

            for(i=0; i<n; ++i)

            {

                for(j=0; j<n; ++j)

                {

                    if(i==j) continue;

                    dp[k][i][j]=Max(dp[k-1][i][j],dp[k-1][i-1][j],dp[k-1][i][j-1],dp[k-1][i-1][j-1]);

                    dp[k][i][j]+=maps[i][k-i]+maps[j][k-j];

                }

            }

        }

        int ans=max(dp[k-1][n-1][n-2],dp[k-1][n-2][n-1])+maps[0][0]+maps[n-1][n-1];

        printf("%d\n",ans);

    }

    return 0;

}


 

 

你可能感兴趣的:(Matrix)