题目链接: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. HBase概念学习(十)HBase与MongDB等NoSQL数据库对照

    转载请注明出处: jiq•钦's technical Blog - 季义钦 一.开篇 淘宝之前使用的存储层架构一直是MySQL数据库,配合以MongDB,Tair等存储. MySQL因为开源,而且生态 ...

  2. Java初学(三)

    一.使用键盘录入数据 三步:1.导入包:import  java.util.Scanner; 2.创建键盘录入对象:Scanner sc=new  Scanner(System.in);   3.通过 ...

  3. 复合主键@IdClass

    有时一个实体的主键可能同时为多个,例如同样是之前使用的“CustomerEO”实体,需要通过name和email来查找指定实体,当且仅当name和email的值完全相同时,才认为是相同的实体对象.要配 ...

  4. CMWAP CMWAP是手机上网使用的接入点的名称

    CMWAP 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . CMWAP是手机上网使用的接入点的名称.CMWAP使用HTTP代理协议和WAP网关协议可以访问到Internet.移动用 ...

  5. JavaScript 参数传递与变量复制

            ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值. 基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象.         5 种基本数 ...

  6. 手机wifi密码的保存位置

    subjects:  adj. 受制于...的, 被统治的; n. 主题,学科, 国民 the subjects had to kneel down before the king. kneel -& ...

  7. 谈“技术含量”的问题

    最近又从离职同事那里听到这样的抱怨(原因),说做的事没有技术含量.想一想,从事车载软件开发这个行业快8年了,这个话题似乎从来没有停过.我自己曾经也为自己做的事是否有技术含量而苦恼过,今天就专门花点时间 ...

  8. 导出Excel之Epplus使用教程4(其他设置)

    导出Excel之Epplus使用教程1(基本介绍) 导出Excel之Epplus使用教程2(样式设置) 导出Excel之Epplus使用教程3(图表设置) 导出Excel之Epplus使用教程4(其他 ...

  9. iOS开发之#iPhone6与iPhone6Plus适配#Xcode6.0/Xcode6.1上传应用过程中一些变动以及#解决方案#

    更新时间2014年11月13日  本博文创建时,只有Xcode6.0, Xcode6.0尝试多次,确实如此 之后在6.1版本经博主少量尝试,确实也有如下问题,现更新下博客! iOS8发布之后,苹果强制 ...

  10. Marriage Ceremonies(状态压缩dp)

     Marriage Ceremonies Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu ...