题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5067

题目意思:给出一个 n * m 的方格,每一个小方格(大小为1*1)的值要么为 0 要么为一个正整数。规定是正整数的值得方格个数不超过 10 个。现在问从最左上角的点开始,要经过所有正整数的值的点之后,要返回到最左上角的点的最短路径是多少。

其实为正整数的那些点具体值是什么根本无关紧要。可以先求出所有点到其他点的两两最短路径,然后利用状态压缩 (考虑到只有10个点,状态数最多为2^10)来求出答案),题解是这样说的:

dp[i][j]:表示状态 i 的点被访问过了,当前停留在点 j 需要的最少时间。枚举另一个不在状态 i 内的点 k , 从点 j 走到点 k 的状态转移方程为:

dp[i|(1<<k)][k] = min(dp[i|(1<<k)][k], dp[i][j] + dist(j, k))

其中,dist[j][k] 表示从点 j 与 点 k 的最短距离。所以可以利用 bfs(当然有更简单的解法,这里我是为了练手而已) 求出以每一个点作为出发点,求出以这个点到其他所有点的最短距离。

代码中的 dp 计算,和方程有一点点不同。有些地方不太理解,先留着吧。。。

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std; const int maxn = + ;
const int INF = 0x3f3f3f3f;
int n, m, cnt, st[maxn], end[maxn];
int vis[maxn][maxn], hs[maxn][maxn];
int dp[maxn][<<], dist[maxn][maxn]; int dx[] = {, , , -};
int dy[] = {, , -, }; struct node
{
int x, y;
int step;
} cur, tmp; queue<node> q; void bfs(int id)
{
while (!q.empty())
q.pop();
memset(vis, , sizeof(vis));
tmp.x = st[id], tmp.y = end[id];
tmp.step = dist[id][id] = ;
q.push(tmp);
vis[st[id]][end[id]] = ; while (!q.empty())
{
tmp = q.front();
q.pop(); for (int i = ; i < ; i++)
{
int tx = tmp.x + dx[i];
int ty = tmp.y + dy[i];
if (tx >= && tx <= n && ty >= && ty <= m && !vis[tx][ty])
{
vis[tx][ty] = ;
cur.x = tx;
cur.y = ty;
cur.step = tmp.step + ;
if (hs[tx][ty] != -) // the target point's id
dist[id][hs[tx][ty]] = cur.step;
q.push(cur);
}
}
}
} void Init()
{
memset(hs, -, sizeof(hs));
int val;
cnt = ;
for (int i = ; i <= n; i++)
{
for (int j = ; j <= m; j++)
{
scanf("%d", &val);
if (val || i == && j == )
{
st[cnt] = i;
end[cnt] = j;
hs[i][j] = cnt++; // 为每一个大于0的点(最多只有10个)编号,第一个点编号为0而不是1
}
}
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif while (scanf("%d%d", &n, &m) != EOF)
{
Init();
for (int i = ; i < cnt; i++) // the shortest path from point i to other points
bfs(i);
int status = <<cnt;
memset(dp, 0x3f, sizeof(dp)); dp[][] = ;
for (int i = ; i < status; i++)
{
for (int j = ; j < cnt; j++)
{
if (dp[j][i] != INF)
{
for (int k = ; k < cnt; k++)
{
if (!(i & (<<k))) // 点k不包含在状态i上
dp[k][i|(<<k)] = min(dp[k][i|(<<k)], dp[j][i]+dist[j][k]);
}
}
}
}
printf("%d\n", dp[][status-]);
}
return ;
}

代码中最后的输出 dp[0][status-1] 很明显就是从最左上角的点出发,经过所有正整数点的最短距离。不过为什么求的时候与二维数组dp[][]不同,这个确实不太理解。

  精简版:

  

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long Int;
typedef pair<int,int>pi;
int n,m;
vector<pi>V;
int Map[][];
int dp[][];
int getdis(int u,int v)
{
if(!u)return V[v-].first+V[v-].second-;
u--;v--;
return abs(V[v].first-V[u].first)+abs(V[v].second-V[u].second);
}
void up(int &x,int y)
{
if(x==-||x>y)x=y;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
V.clear();
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
{
int u;
scanf("%d",&u);
if(i==&&j==)continue;
if(u>)
V.push_back(pi(i,j));
}
if(!V.size()){puts("");continue;}
memset(dp,-,sizeof(dp));
dp[][]=;
int mx=(<<V.size())-;
for(int j=;j<mx;j++)
for(int k=;k<=V.size();k++)
if(dp[j][k]>=)
{
for(int p=;p<V.size();p++)
if((j&(<<p))==)
{
up(dp[j|(<<p)][p+],dp[j][k]+getdis(k,p+));
}
}
int ans=-;
for(int i=;i<V.size();i++)
if(dp[mx][i+]>=)
up(ans,dp[mx][i+]+getdis(,i+));
printf("%d\n",ans);
}
}

BestCoder14 1002.Harry And Dig Machine(hdu 5067) 解题报告的更多相关文章

  1. BestCoder6 1002 Goffi and Squary Partition(hdu 4982) 解题报告

    题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?pid=1002&cid=530 (格式有一点点问题,直接粘 ...

  2. BestCoder22 1002.NPY and arithmetic progression(hdu 5143) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5143 题目意思:给出 1, 2, 3, 4 的数量,分别为a1, a2, a3, a4,问是否在每个数 ...

  3. BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5087 题目意思:找出第二个最长递增子序列,输出长度.就是说,假如序列为 1 1 2,第二长递增子序列是 ...

  4. BestCoder20 1002.lines (hdu 5124) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5124 题目意思:给出 n 条线段,每条线段用两个整数描述,对于第 i 条线段:xi,yi 表示该条线段 ...

  5. BestCoder18 1002.Math Problem(hdu 5105) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5105 题目意思:给出一个6个实数:a, b, c, d, l, r.通过在[l, r]中取数 x,使得 ...

  6. BestCoder17 1002.Select(hdu 5101) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5101 题目意思:给出 n 个 classes 和 Dudu 的 IQ(为k),每个classes 都有 ...

  7. BestCoder15 1002.Instruction(hdu 5083) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5083 题目意思:如果给出 instruction 就需要输出对应的 16-bit binary cod ...

  8. BestCoder12 1002.Help him(hdu 5059) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5059 题目意思:就是输入一行不多于 100 的字符串(除了'\n' 和 '\r' 的任意字符),问是否 ...

  9. BestCoder10 1002 Revenge of GCD(hdu 5019) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5019 题目意思:给出 X 和 Y,求出 第 K 个 X 和 Y 的最大公约数. 例如8 16,它们的公 ...

随机推荐

  1. Oracle写函数读写日志实例

    1.用DBA登录赋权限create or replace directory D_OUTPUT as 'D:\TEMP'; grant read,write on directory D_OUTPUT ...

  2. PHP Web System Optimization(undone)

    目录 . 引言 . PHP Pool . listen . Process Manage(PM) . pm.max_children . PHP DB Connection Pool(数据库连接池) ...

  3. wifi与wimax

    这几天在看文献中看到802.11a,802.11n和802.16e这几种无信通信协议标准,在网上查了相关资料后,看到有个帖子总结得不错,故将其转载过来. 转:http://blog.csdn.net/ ...

  4. node相关的精典材料

    node.js电子书 了不起的Node.js 深入浅出Node.js node.js入门经典 node.js开发指南 node.js相关优秀博文 官网 Infoq深入浅出Node.js系列(进阶必读) ...

  5. BUAA1389愤怒的DZY(最大值最小化)

    http://acm.buaa.edu.cn/problem/1389/ 愤怒的DZY[问题描述]“愤怒的小鸟”如今已经是家喻户晓的游戏了,机智的WJC最近发明了一个类似的新游戏:“愤怒的DZY”.游 ...

  6. 分享一段Java搞笑的代码注释

    今天在群里看到有人分享了一段搞笑的注释代码,觉得挺好玩的,在这里收藏一下 // _ooOoo_ // o8888888o // 88" . "88 // (| -_- |) // ...

  7. XUnit学习

    1.建立测试单元项目 2.引用XUnit.dll或者在Nuget里安装XUnit 3.安装Nuget->xUnit.net[Runner: Visual Studio] 4.打开 测试-> ...

  8. jquery------导入jquery.2.2.3.min.js

    问题: 导入jquery.2.2.3.min.js后MyEclipse会提示代码有错误 方法: 选中jquery.2.2.3.min.js->右键->选择“MyEclipse”中的“Exc ...

  9. Why The Golden Age Of Machine Learning is Just Beginning

    Why The Golden Age Of Machine Learning is Just Beginning Even though the buzz around neural networks ...

  10. 神器Alfred使用

    神器官网:http://www.alfredapp.com/ 许多人装好了之后就再也没有怎么使用过,这软神器, 一直不明白它为什么叫神器,最近研究了一下,真的是,很多东西我们没有好好利用 部分使用功能 ...