vijos:P1285佳佳的魔法药水
Posted vCoders
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vijos:P1285佳佳的魔法药水相关的知识,希望对你有一定的参考价值。
背景
发完了k张照片,佳佳却得到了一个坏消息:他的MM得病了!佳佳和大家一样焦急万分!治好MM的病只有一种办法,那就是传说中的0号药水……怎么样才能得到0号药水呢?你要知道佳佳的家境也不是很好,成本得足够低才行……
描述
得到一种药水有两种方法:可以按照魔法书上的指导自己配置,也可以到魔法商店里去买——那里对于每种药水都有供应,虽然有可能价格很贵。在魔法书上有很多这样的记载:1份A药水混合1份B药水就可以得到1份C药水。(至于为什么1+1=1,因为……这是魔法世界)好了,现在你知道了需要得到某种药水,还知道所有可能涉及到的药水的价格以及魔法书上所有的配置方法,现在要问的就是:1.最少花多少钱可以配制成功这种珍贵的药水;2.共有多少种不同的花费最少的方案(两种可行的配置方案如果有任何一个步骤不同则视为不同的)。假定初始时你手中并没有任何可以用的药水。
格式
输入格式
第一行有一个整数N(N<=1000),表示一共涉及到的药水总数。药水从0~N-1顺序编号,0号药水就是最终要配制的药水。
第二行有N个整数,分别表示从0~N-1顺序编号的所有药水在魔法商店的价格(都表示1份的价格)。
第三行开始,每行有3个整数A、B、C,表示1份A药水混合1份B药水就可以得到1份C药水。注意,某两种特定的药水搭配如果能配成新药水的话,那么结果是唯一的。也就是说不会出现某两行的A、B相同但C不同的情况。
输出格式
输出两个用空格隔开的整数,分别表示得到0号药水的最小花费以及花费最少的方案的个数。
输入:
7
10 5 6 3 2 2 3
1 2 0
4 5 1
3 6 2
输出:
10 3
思路:一开始以为是树形DP,不料数据中存在环,如a+b->c,a+c->,b+c->a.结果只过了第一个数据,其他Runtime error
#include<cstdio> #include<cstring> #include<vector> using namespace std; const int MAXN=10005; struct P{ int x,y; P(){} P(int x,int y) { this->x=x; this->y=y; } }; vector<P> mp[MAXN]; vector<int> minv[MAXN]; int vis[MAXN]; int n,val[MAXN]; void dfs(int u) { for(int i=0;i<mp[u].size();i++) { P p=mp[u][i]; if(!vis[p.x]) dfs(p.x); if(!vis[p.y]) dfs(p.y); for(int i=0;i<minv[p.x].size();i++) { int z=minv[p.x][i]; for(int j=0;j<minv[p.y].size();j++) { minv[u].push_back(z+minv[p.y][j]); } } } minv[u].push_back(val[u]); vis[u]=1; } int mn; int solve(int u) { mn=0x7f7f7f7f; for(int i=0;i<minv[u].size();i++) { if(minv[u][i]<mn) { mn=minv[u][i]; } } int cnt=0; for(int i=0;i<minv[u].size();i++) { if(minv[u][i]==mn) cnt++; } return cnt; } int main() { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&val[i]); } int a,b,c; while(scanf("%d%d%d",&a,&b,&c)!=EOF) { if(a==-1) break; mp[c].push_back(P(a,b)); } dfs(0); int res=solve(0); printf("%d %d\n",mn,res); return 0; }
题解这样说:每次找到一个最小花费的药水i,再和已经确定的花费的药水且是i的兄弟的药水j, 用i,j更新其父药水fa[i][j].那么该题就成模板题了。
#include<cstdio> #include<cstring> using namespace std; const int MAXN=1005; int d[MAXN]; int fa[MAXN][MAXN]; int n; int vis[MAXN]; int tot[MAXN]; int main() { scanf("%d",&n); memset(fa,-1,sizeof(fa)); for(int i=0;i<n;i++) { scanf("%d",&d[i]); tot[i]=1; } int a,b,c; while(scanf("%d%d%d",&a,&b,&c)!=EOF) { if(a==-1) break; fa[a][b]=c; fa[b][a]=c; } while(true) { int mn=0x7f7f7f7f; int k; for(int i=0;i<n;i++) { if(!vis[i]&&mn>d[i]) { mn=d[i]; k=i; } } if(mn==0x7f7f7f7f) break; vis[k]=1; for(int i=0;i<n;i++) { int par=fa[k][i]; if(vis[i]&&par!=-1) { if(d[par]>d[k]+d[i]) { d[par]=d[k]+d[i]; tot[par]=tot[k]*tot[i]; } else if(d[par]==d[k]+d[i]) { tot[par]+=tot[k]*tot[i]; } } } } printf("%d %d\n",d[0],tot[0]); return 0; }
以上是关于vijos:P1285佳佳的魔法药水的主要内容,如果未能解决你的问题,请参考以下文章