HDU 4370 0 or 1(最短路)

本博客探讨了在给定条件约束下求解矩阵X的最优解,旨在最小化矩阵C与X的乘积之和。通过实例分析和算法实现,详细解释了解决过程及其实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Given a n*n matrix Cij (1<=i,j<=n),We want to find a n*n matrix Xij (1<=i,j<=n),which is 0 or 1.

 

Besides,Xij meets the following conditions:

 

1.X12+X13+...X1n=1

2.X1n+X2n+...Xn-1n=1

3.for each i (1<i<n), satisfies Xki (1<=k<=n)=Xij (1<=j<=n).

 

For example, if n=4,we can get the following equality:

 

X12+X13+X14=1

X14+X24+X34=1

X12+X22+X32+X42=X21+X22+X23+X24

X13+X23+X33+X43=X31+X32+X33+X34

 

Now ,we want to know the minimum of Cij*Xij(1<=i,j<=n) you can get.

Input

The input consists of multiple test cases (less than 35 case).

For each test case ,the first line contains one integer n (1<n<=300).

The next n lines, for each lines, each of which contains n integers, 

illustrating the matrix C, The jth integer on ith line is Cij(0<=Cij<=100000).

Output

For each case, output the minimum of Cij*Xij you can get.

Sample Input

4
1 2 4 10
2 0 1 1
2 2 0 5
6 3 1 2

Sample Output

3

Hint

For sample, X12=X24=1,all other Xij is 0.



最短路

#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
int date[310][310];
int n;
/*const int maxe=310;
int dis[maxe];
bool v[maxe];
void dijkstra()
{
	for (int i=1;i<=n;++i)
	{
		dis[i]=1e9;
	}
	dis[1]=0;
	memset(v,0,sizeof(v));
	for (int i=1;i<=n;++i)
	{
		int mark=-1,mindis=1e9;
		for (int j=1;j<=n;++j)
		{
			if(!v[j]&&dis[j]<mindis)
			{
				mindis=dis[j];
				mark=j;
			}
			v[mark]=1;
			for (int j=1;j<=n;++j) 
				if (!v[j])
				{
					dis[j]=dis[j]<(dis[mark]+date[mark][j])?dis[j]:(dis[mark]+date[mark][j]);
					printf("%d %d\n",j,dis[j]);
					}
		}
	}
	return ;
}*/
const int INF=0x3f3f3f3f;
const int MAXN=330;
int dis[MAXN];
int que[MAXN];
bool vis[MAXN];

void SPFA(int start,int n)
{
    int front=0,rear=0;
    for(int v=1;v<=n;v++)
    {
        if(v==start)
        {
            dis[v]=INF;
            vis[v]=false;
        }
        else if(date[start][v]!=INF)
        {
            dis[v]=date[start][v];
            que[rear++]=v;
            vis[v]=true;
        }
        else
        {
            dis[v]=INF;
            vis[v]=false;
        }
    }

    while(front!=rear)
    {
        int u=que[front++];
        for(int v=1;v<=n;v++)
        {
            if(dis[v]>dis[u]+date[u][v])
            {
                dis[v]=dis[u]+date[u][v];
                if(!vis[v])
                {
                    vis[v]=true;
                    que[rear++]=v;
                    if(rear>=MAXN) rear=0;
                }
            }
        }
        vis[u]=false;
        if(front>=MAXN)front=0;
    }

}
int main ()
{
	//freopen ("heh.txt","r",stdin);
	while (scanf("%d",&n)!=EOF)
	{
		for (int i=1;i<=n;i++)
		{
			for (int j=1;j<=n;j++)
			{
				scanf("%d",&date[i][j]);
			}
			date[i][i]=0;
		}
		SPFA(1,n);
      	  	int ans=dis[n];
       	 	int loop1=dis[1];
       	 	SPFA(n,n);
        	int loopn=dis[n];
      	  	ans=min(ans,loop1+loopn);
        	printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值