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 }