1. 程式人生 > >P1194 買禮物

P1194 買禮物

i++ include turn col 100% tro memset stream 發現

P1194 買禮物

題目描述

又到了一年一度的明明生日了,明明想要買B樣東西,巧的是,這B樣東西價格都是A元。

但是,商店老板說最近有促銷活動,也就是:

如果你買了第I樣東西,再買第J樣,那麽就可以只花K[I,J]元,更巧的是,K[I,J]竟然等於K[J,I]。

現在明明想知道,他最少要花多少錢。

輸入輸出格式

輸入格式:

第一行兩個整數,A,B。

接下來B行,每行B個數,第I行第J個為K[I,J]。

我們保證K[I,J]=K[J,I]並且K[I,I]=0。

特別的,如果K[I,J]=0,那麽表示這兩樣東西之間不會導致優惠。

輸出格式:

僅一行一個整數,為最小要花的錢數。

輸入輸出樣例

輸入樣例#1:
【樣例輸入1】
1 1
0
【樣例輸入2】
3 3
0 2 4
2 0 2
4 2 0
輸出樣例#1:
【樣例輸出1】
1
【樣例輸出2】
7

說明

樣例解釋2

先買第2樣東西,花費3元,接下來因為優惠,買1,3樣都只要2元,共7元。

(同時滿足多個“優惠”的時候,聰明的明明當然不會選擇用4元買剩下那件,而選擇用2元。)

數據規模

對於30%的數據,1<=B<=10。

對於100%的數據,1<=B<=500,0<=A,K[I,J]<=1000。

分析:

這個題目我們要買所有的商品,只需要把所有的點都連起來就可以了。所以顯然就是一個最小生成樹。而且我們也會發現選商品的過程和最小生成樹的選取一個點非常相似。而且,整個價格是確定好的,最優解只有一種(可能多個),所以在最開始從任意一個點出發都是一樣的。minn[i]記錄買i東西的最低價。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define f(ii,l,r) for(int ii=l;ii<=r;ii++)
 5 #define maxn 501
 6 using namespace std;
 7 long long  ans=0,v;
 8 int n,m,x,y;
 9 long long g[maxn][maxn],minn[maxn],q;
10 bool vis[maxn];
11 int main() {
12     cin>>q>>n;
13 f(i,1,n) 14 f(j,1,n){ 15 //讀入邊 16 cin>>g[i][j]; 17 if(g[i][j]==0) 18 g[i][j]=q; 19 } 20 memset(minn,0x3f,sizeof(minn)); 21 //第一個點按原價買 22 //minn[i]記錄買i東西的最低價 23 minn[1]=q; 24 memset(vis,0,sizeof(vis)); 25 // 26 f(i,1,n) { 27 int k=0; 28 f(j,1,n) 29 //找最優點 30 if(!vis[j]&&(minn[j]<minn[k])) 31 k=j; 32 vis[k]=true; 33 //用最優點更新所有邊 34 f(j,1,n) 35 if(!vis[j]&&(minn[j]>g[k][j])) 36 minn[j]=g[k][j]; 37 } 38 f(i,1,n) 39 ans+=minn[i]; 40 cout<<ans<<endl; 41 return 0; 42 }

P1194 買禮物