hdu 4370 0 or 1(将数学问题转化为最短路)
2016-08-10 17:38
411 查看
题目链接
0 or 1
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1912 Accepted Submission(s): 575
Problem 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.
Hint
For sample, X12=X24=1,all other Xij is 0.
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 j-th integer on i-th 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
Author
Snow_storm
Source
2012 Multi-University Training Contest 8
这个题解很详细
在计算1和n的自环是要注意自环最小花费不一定是只经过除起点以外的一个点,因为这个路径虽说是双向的,但是从i到j的花费和从j到i的花费不相等,所以可能从起点经过多个点后再回来的总花费会比只经过一个点的最小花费低。因此使用了改进的spfa。详见代码。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> using namespace std; const int maxn=300+10; const int inf=0x3f3f3f3f; int n; int cost[maxn][maxn]; int d[maxn],inq[maxn]; void spfa(int s) //改进的spfa { memset(inq,0,sizeof(inq)); queue<int> q; for(int i=1;i<=n;i++) { if(i==s) { d[s]=inf;continue; } d[i]=cost[s][i]; inq[i]=1; q.push(i); } while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=0; for(int i=1;i<=n;i++) { if(d[i]>d[u]+cost[u][i]) { d[i]=d[u]+cost[u][i]; if(inq[i]) continue; inq[i]=1; q.push(i); } } } } int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&cost[i][j]); int ans=inf; spfa(1); int loop1=d[1]; ans=min(ans,d ); spfa(n); int loopn=d ; ans=min(ans,loop1+loopn); printf("%d\n",ans); } }
循环队列版本:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=300+10;
const int inf=0x3f3f3f3f;
int n;
int cost[maxn][maxn];
int d[maxn],inq[maxn];
int que[maxn];
void spfa(int s)
{
memset(inq,0,sizeof(inq));
memset(que,0,sizeof(que));
queue<int> q;
int head=0,rear=0;
for(int i=1;i<=n;i++)
{
if(i==s)
{
d[s]=inf;continue;
}
d[i]=cost[s][i];
inq[i]=1;
que[rear++]=i;
}
while(head!=rear)
{
int u=que[head++];
inq[u]=0;
for(int i=1;i<=n;i++)
{
if(d[i]>d[u]+cost[u][i])
{
d[i]=d[u]+cost[u][i];
if(inq[i]) continue;
inq[i]=1;
que[rear++]=i;
if(rear>=maxn) rear=0;
}
}
if(head>=maxn) head=0;
}
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&cost[i][j]);
int ans=inf;
spfa(1);
int loop1=d[1];
ans=min(ans,d
);
spfa(n);
int loopn=d
;
ans=min(ans,loop1+loopn);
printf("%d\n",ans);
}
}
相关文章推荐
- HDU-4370 0 or 1(最短路[Dijkstra])
- HDU 4370 0 or 1(最短路)
- HDU-4370 0 or 1( 最短路 )
- HDU 4370 0 or 1 [01规划最短路]
- HDU 4370 0 or 1(12年多校by uestc 0/1规划,最短路)
- HDU 4370 0 or 1 (最短路+最小环)
- HDU 4370 0 or 1(最短路)by Kuangbin
- HDU 4370 0 or 1(巧妙思路转化,0/1规划,最短路SPFA)
- Hdu 4370 0 or 1【思维建图+最短路】好题!好题!好题!
- HDU 4370 0 or 1 【抽象最短路】
- HDU-4370 '0 or 1' 最短路 要考虑连通性
- 0 or 1 HDU - 4370(最短路)
- HDU 4370 0 or 1(最短路)
- HDU 4370 0 or 1(最短路)
- hdu 4370 0 or 1 (最短路)
- HDU 4370 0 or 1(最短路)
- 最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter
- hdu 4473 Exam (思维题 问题转化)
- HDU 2199 || HDU 2899 (二分查找+数学问题)
- 最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter