感觉自己已经有N久没有写过DFS算法了,因为这道题目在DFS的过程中会保留和计算一些值,所以导致程序看起来有点丑陋。话不多说 贴题说思路,目前水平有限,发博客的主要原因是要写给自己,作为一段时间学习的印证吧。
题目地址: http://poj.org/problem?id=1062
这道题目也是POJ上 少有的中文题目了,所以很快能读懂。不过回想去年这道题其实自己尝试过一次,不过没有解出来,后来就放下了,今天又把那个ACM题目分类拿出来,准备重拾这些内容的时候,这个题目就又回来了。
开始不知道怎么做,无意之间看到discuss里有人说dfs,沿着说着思路也就想通了。
如果将物品理解成图中的节点,那么两个物品直接的可以交换的关系,就可以理解成有向图直接邻接关系,对于任意一种物品,都可以直接用金币换,或者提供其他交换物品和金币。所以我们可以用dfs遍历这个图,在遍历的过程中求出最小的代价,就可以求出最后的结果。
代码如下:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define PRODUCT_NUM 101 struct Product { int Level; int Prize; }; int matExchange[PRODUCT_NUM][PRODUCT_NUM]; int maxDif; int nProduct; Product allProduct[PRODUCT_NUM]; bool visited[PRODUCT_NUM]; int dfsFindMinPrize(int f, int maxLevel, int minLevel) { int GetPrize = allProduct[f].Prize; int exchangedPrize; visited[f] = true; int Level; int newMaxLevel, newMinLevel; for(int i = 1; i <= nProduct; i++) { Level = allProduct[i].Level; newMaxLevel = maxLevel > Level ? maxLevel : Level; newMinLevel = minLevel < Level ? minLevel : Level; if(matExchange[f][i]&& !visited[i] && (newMaxLevel - newMinLevel) <= maxDif) { exchangedPrize = dfsFindMinPrize(i, newMaxLevel, newMinLevel); exchangedPrize += matExchange[f][i]; if(exchangedPrize < GetPrize) { GetPrize = exchangedPrize; } } } visited[f] = false; return GetPrize; } int main() { int i,j; int prize, level, replace; int replaceWith, replacePrize; while(scanf("%d%d", &maxDif, &nProduct) != EOF) { memset(matExchange, 0, sizeof(matExchange)); for( i = 1; i <= nProduct; i++) { scanf("%d%d%d", &prize, &level, &replace); allProduct[i].Prize = prize; allProduct[i].Level = level; for( j = 0; j < replace; j++) { scanf("%d%d", &replaceWith, &replacePrize); matExchange[i][replaceWith] = replacePrize; } } memset(visited, 0, sizeof(visited)); int prize = dfsFindMinPrize(1,allProduct[1].Level , allProduct[1].Level); printf("%d\n", prize); } return 0; }
在dfs过程中,因为可以直接用金币交换到物体,所以可以初始化物体 价格就是物体的 金币价格。
然后dfs过程中,如果出现比当前价格小的交换方式,就采用新的交换方式。
最后返回最小交换价格~