1. 程式人生 > >洛谷—— P1875 佳佳的魔法藥水

洛谷—— P1875 佳佳的魔法藥水

最終 整數 成功 所有 char har 一行 getc 配置

P1875 佳佳的魔法藥水

題目描述

發完了 k 張照片,佳佳卻得到了一個壞消息:他的 MM 得病了!佳佳和大家一樣焦急 萬分!治好 MM 的病只有一種辦法,那就是傳說中的 0 號藥水 ……怎麽樣才能得到 0 號藥 水呢?你要知道佳佳的家境也不是很好,成本得足夠低才行……

題目描述:

得到一種藥水有兩種方法:可以按照魔法書上的指導自己配置,也可以到魔法商店裏去

買——那裏對於每種藥水都有供應,雖然有可能價格很貴。在魔法書上有很多這樣的記載:

1 份 A 藥水混合 1 份 B 藥水就可以得到 1 份 C 藥水。(至於為什麽 1+1=1,因為……這是魔

法世界)好了,現在你知道了需要得到某種藥水,還知道所有可能涉及到的藥水的價格以及

魔法書上所有的配置方法,現在要問的就是:1.最少花多少錢可以配制成功這種珍貴的藥水;

2.共有多少種不同的花費最少的方案(兩種可行的配置方案如果有任何一個步驟不同則視為 不同的)。假定初始時你手中並沒有任何可以用的藥水。

輸入輸出格式

輸入格式:

第一行有一個整數 N,表示一共涉及到的藥水總數。藥水從 0~N­1 順序編號,0 號藥水就是 最終要配制的藥水。

第二行有 N 個整數,分別表示從 0~N­1 順序編號的所有藥水在魔法商店的價格(都表示 1 份的價格)。

第三行開始,每行有 3 個整數 A、B、C,表示 1 份 A 藥水混合 1 份 B 藥水就可以得到 1 份 C 藥水。註意,某兩種特定的藥水搭配如果能配成新藥水的話,那麽結果是唯一的。也就是 說不會出現某兩行的 A、B 相同但 C 不同的情況。

輸入以一個空行結束。

輸出格式:

輸出兩個用空格隔開的整數,分別表示得到 0 號藥水的最小花費以及花費最少的方案的個

數。

輸入輸出樣例

輸入樣例#1:
7 
10 5 6 3 2 2 3 
1 2 0 
4 5 1 
3 6 2
輸出樣例#1:
10 3

說明

樣例說明:

最優方案有 3 種,分別是:直接買 0 號藥水;買 4 號藥水、5 號藥水配制成 1 號藥水,直接 買 2 號藥水,然後配制成 0 號藥水;買 4 號藥水、5 號藥水配制成 1 號藥水,買 3 號藥水、6 號藥水配制成 2,然後配制成 0。

dijkstra求最短路

再求方案數的時候分兩種情況

1:兩個原料藥水合成的藥水的原本最小花費等於原料藥水的總花費,那麽合成藥水的方案數就需要在原本的基礎上加上兩個原料藥水方案的乘積

2:兩個原料藥水合成的藥水的原本最小花費小於原料藥水的總花費,那麽合成藥水的方案數就等於兩個原料藥水方案的乘積

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 1010
#define maxn 9999999
using namespace std;
bool vis[N];
int n,x,y,z,ans1,ans2,sum[N],dis[N],f[N][N];
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1; ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();}
    return x*f;
}
int dijkstra()
{
    for(int i=1;i<=n;i++)
    {
        int x,t=maxn;
        for(int j=1;j<=n;j++)
          if(!vis[j]&&dis[j]<t) 
           x=j,t=dis[j];
        if(t==maxn) break;
        vis[x]=true;
        for(int j=1;j<=n;j++)
        {
            if(!f[x][j]) continue;
            if(!vis[j]) continue;
            if(dis[f[x][j]]>t+dis[j]) 
             dis[f[x][j]]=t+dis[j],sum[f[x][j]]=sum[x]*sum[j];
            else if(dis[f[x][j]]==t+dis[j]) sum[f[x][j]]+=sum[x]*sum[j];
        }
    }
    ans1=dis[1],ans2=sum[1];
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++) dis[i]=read(),sum[i]=1;
    while(scanf("%d%d%d",&x,&y,&z)!=EOF)
    {
        f[x+1][y+1]=z+1;
        f[y+1][x+1]=z+1;
    }
    dijkstra();
    printf("%d %d",ans1,ans2);
    return 0;
}

洛谷—— P1875 佳佳的魔法藥水