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 然后
X23 然后 X3n 这样 虽然选的数多,但是总和可能会更小。 所以从我刚刚举出的例子 就可以抽象出 第一次选X1i (正好i能不为1)然后转到 第i行 再选Xij
再转到j行 这样一直选到Xkn为止。和求从1到n的最短路的操作一样。但还存在一些不同, 因为如果是按照X1i →
Xij →Xj1。这样返回1,再选择一个k从k到n也是成立的。所以可以要分别处理出每个点到一的最短路,和每个点到n的最短路。
1.X12+X13+...X1n=1
2.X1n+X2n+...Xn-1n=1
3.对于每一个小于n的 i 都有第i行和第i列的和相等
最后要使2个方阵对应位置乘起来的总和最小。
初步的抽象一下,并不需要真正的构造出第二个方阵,而只是在给出的方阵之中按条件选一些位置加起来就是答案了。所以我当时就把这题当成水题开始编(>﹏<)。
对方阵中的数进行选取时,首先比较容易想到的选取是 选X1n 或者 选X1i+Xin。
但其实并不完全,因为我们其实可以选 X12 然后
X23 然后 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; }
相关文章推荐
- 二维数组中的查找-在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- windows下ftp server搭建
- windows服务器下的ftp server搭建
- 字符串匹配的KMP算法
- 使用Matlab结合神经网络模型对多波段影像进行计算
- 索引
- Java 编程语言支持三种循环构造类型
- 剑指offer面试题26-复杂链表的复制
- 每天一个linux命令---tar
- [HDOJ1251]统计难题
- 模板---函数模板
- 总结系列--PackageIManager信息 PackageInfo/ApplicationInfo/ActivityInfo
- Ubuntu 如何定制桌面解放你的个性?
- Qt之界面实现技巧
- MySQL--cmd命令连接mysql
- 有关import reload __import__
- 今天开始要写博文了!
- jQuery性能优化篇
- 多线程开发之一 NSThread
- mysql 中文乱码问题解决