昂贵的聘礼 POJ - 1062
2018-03-14 14:06:05
题意:小花想娶部落里的王子 王子的父亲要求一定数量的金币 困窘的小花还有两外一条出路就是得到另外一件东西与王子的父亲交换 以此来减少金币 同理 可以由别的东西来换取现在需要的东西的优惠 另一个限制条件就是 等级相差k的人不能进行交易 即使是间接交易
思路:建造一棵树 两个节点之间的边权即代表由B事物去换取A事物还需要多少金币 节点用结构体保存 表示这个物品的价格与等级 这样的话 要得到一号节点的王子 就是不断向下搜索 在可以走的条件下(等级限制) 找到尽可能短的路到达一号节点 每一条路径都需要加上末尾节点的值 因为获得最后面的物品也是需要花钱的
现在附上错误代码 错误代码是按照BFS搜下去 dis[]数组保存的是到达一号节点的距离 然后最后吧所有的节点跑一边 找到最小的dis[]+node[i].mon就好
错因:我这里的等级限制是由1号节点得来 然后一直使用的 但是在加入一个新的节点到路径上来的时候 后面的节点的等级限制就发生了改变 例如 1号节点的等级是3 k=1 那么等级限制就是2~4 下一个节点的等级是2 满足要求 但是后面路径上的点的等级限制就变成了2~3
#include<stdio.h> #include<iostream> #include<string.h> #include<queue> using namespace std; #define inf 0x3f3f3f3f int k , n; struct NODE { int mon; int dep; }node[110]; int mp[110][110];//记录图 int dis[110];//记录1号点到其他点的距离 int vis[110];//是否被加入到最短路中 void init() { for(int i=1; i<=n; i++) { dis[i] = inf; for(int j=1; j<=n; j++) { mp[i][j] = inf; } } memset(vis , 0 , sizeof(vis)); } void input() { int num; int id , val; for(int i=1; i<=n; i++) { scanf("%d%d%d" , &node[i].mon , &node[i].dep , &num); for(int j=1; j<=num; j++) { scanf("%d%d" , &id , &val); mp[i][id] = val; } } } void solve() { int l , r; int f; l = max(0 , node[1].dep-k); r = node[1].dep+k; dis[1] = 0; while( true ) { // printf("+++++++++++ "); int minn = inf; int whe = -1; for(int i=1; i<=n; i++) { if(vis[i]==0 && node[i].dep>=l && node[i].dep<=r && dis[i]<minn) { minn = dis[i]; whe = i; } } if(whe == -1) break; vis[whe] = 1; // printf("%d...... " , whe); for(int i=1; i<=n; i++) { if(vis[i]==0 && dis[whe]+mp[whe][i]<dis[i]) { dis[i] = dis[whe]+mp[whe][i]; } } } } void ans() { int minn = inf; for(int i=2; i<=n; i++) { dis[i] += node[i].mon; if(vis[i]==1 && dis[i]<minn) { minn = dis[i]; } } if(minn==inf) printf("%d " , node[1].mon); else printf("%d " , minn); } int main() { while( scanf("%d%d" , &k , &n) != EOF ) { init(); input(); solve(); ans(); } return 0; }
正确代码
使用DFS来写 每一条路径上不停地更新等级限制
///错因 没有更新限制的等级的上下界 ///此时不能用广搜了 这个想法是不对的 应该用深搜 不断更新上下界 #include<stdio.h> #include<iostream> #include<string.h> #include<queue> using namespace std; #define inf 1000000000 int k , n; struct NODE { int mon; int dep; } node[110]; int mp[110][110];//记录图 int dis[110];//记录1号点到其他点的距离 int vis[110];//是否被加入到最短路中 int ans; int l , r; void init() { for(int i=1; i<=n; i++) { dis[i] = inf; for(int j=1; j<=n; j++) { mp[i][j] = inf; } } memset(vis , 0 , sizeof(vis)); } void input() { int num; int id , val; for(int i=1; i<=n; i++) { scanf("%d%d%d" , &node[i].mon , &node[i].dep , &num); for(int j=1; j<=num; j++) { scanf("%d%d" , &id , &val); mp[i][id] = val; } } } void dfs(int num) { int tmp1 , tmp2; for(int i=1; i<=n; i++) { if(vis[i]==0 && node[i].dep>=l && node[i].dep<=r) { if((num==1&&mp[1][i]<dis[i]) || dis[num]+mp[num][i]<dis[i]) { vis[i] = 1; tmp1 = l; tmp2 = r; l = max(l , node[i].dep-k); r = min(r , node[i].dep+k); dis[i] = dis[num]+mp[num][i]; dfs(i); vis[i] = 0; l = tmp1; r = tmp2; } } } ans = min(ans , dis[num]+node[num].mon); } //void solve() //{ // int l , r; // int f; // l = max(0 , node[1].dep-k); // r = node[1].dep+k; // dis[1] = 0; // while( true ) // { //// printf("+++++++++++ "); // int minn = inf; // int whe = -1; // for(int i=1; i<=n; i++) // { // if(vis[i]==0 && node[i].dep>=l && node[i].dep<=r && dis[i]<minn) // { // minn = dis[i]; // whe = i; // } // } // if(whe == -1) // break; // vis[whe] = 1; //// printf("%d...... " , whe); // for(int i=1; i<=n; i++) // { // if(vis[i]==0 && dis[whe]+mp[whe][i]<dis[i]) // { // dis[i] = dis[whe]+mp[whe][i]; // } // } // } //} //void ans() //{ // int minn = inf; // for(int i=2; i<=n; i++) // { // dis[i] += node[i].mon; // if(vis[i]==1 && dis[i]<minn) // { // minn = dis[i]; // } // } // if(minn==inf) // printf("%d " , node[1].mon); // else // printf("%d " , minn); //} int main() { while( scanf("%d%d" , &k , &n) != EOF ) { init(); input(); ans = node[1].mon; l = max(0 , node[1].dep-k); r = node[1].dep+k; vis[1] = 1; dis[1] = 0; // for(int i=2; i<=n; i++) // { // if(node[i].dep>=l && node[i].dep<=r) // { // dis[i] = mp[1][i]; // } // } dfs(1); printf("%d ", ans); // ans(); } return 0; }