您的位置:首页 > 其它

HDU 4370 0 or 1

2015-08-24 23:04 267 查看
题意:给你个方阵,你得再构造一个同等大小的方阵(只包含0和1)满足以下3条:

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

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

3.对于每一个小于n的 i 都有第i行和第i列的和相等

最后要使2个方阵对应位置乘起来的总和最小。

初步的抽象一下,并不需要真正的构造出第二个方阵,而只是在给出的方阵之中按条件选一些位置加起来就是答案了。所以我当时就把这题当成水题开始编(>﹏<)。

对方阵中的数进行选取时,首先比较容易想到的选取是 选X1n 或者 选X1i+Xin。

但其实并不完全,因为我们其实可以选 X12 然后
X
23 然后 X3n 这样 虽然选的数多,但是总和可能会更小。 所以从我刚刚举出的例子 就可以抽象出 第一次选X1i (正好i能不为1)然后转到 第i行 再选Xij
再转到j行 这样一直选到Xkn为止。和求从1到n的最短路的操作一样。但还存在一些不同, 因为如果是按照X1i →
Xij →Xj1。这样返回1,再选择一个k从k到n也是成立的。所以可以要分别处理出每个点到一的最短路,和每个点到n的最短路。

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include<set>
#include<stack>
#define bug puts("bugbugbug");
using namespace std;
const int inf=10000000;
typedef long long ll;
const int M=300+5;
int mapp[M][M];
int dist[M];
bool mark[M];
int n;
void dijk (int u)
{
    int i, j, mins, v;
    for (i = 1; i <= n; i++)
    {
        dist[i] = mapp[u][i];
        mark[i] = false;
    }
    mark[u] = true;
    dist[u] = 0;
    while (1)
    {
        mins = inf;
        for (j = 1; j <= n; j++)
            if (!mark[j] && dist[j] < mins)
                mins = dist[j], v = j;
        if (mins == inf)
            break;
        mark[v] = true;
        for (j = 1; j <= n; j++)
            if (!mark[j] && dist[v] + mapp[v][j] < dist[j])
                dist[j] = dist[v] + mapp[v][j];
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                scanf("%d",&mapp[i][j]);
                for(int i=1;i<=n;i++)
                    mapp[i][i]=inf;
    int ans=mapp[1]
;
    n--;
    dijk(1);
    int minn=inf;
    for(int i=1;i<=n;i++){
    minn=min(minn,dist[i]+mapp[i][1]);
    ans=min(ans,dist[i]+mapp[i][n+1]);
    }
    n++;
    dijk(n);
    for(int i=2;i<=n;i++)
        ans=min(ans,minn+dist[i]+mapp[i]
);
    printf("%d\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: