poj1062昂貴的聘禮
阿新 • • 發佈:2017-05-07
con 答案 ons can 得到 繪圖 cpp 。。 ret
這個題目我最開始看題目看了半天,看不懂。。
可是通過看例子及答案最終看懂了。
。。
首先先解決等級的關系。
。假設等級越界。則不能交換。。所以原本等級的界限是
[rank[1]-m,rank[1]+m],可是這個邊界裏面會出現等級僅僅差大於m。所以等級的區間應該是
[rank[1]-m,rank[1]],[rank[1]-m+1,rank[1]+1]............等等。所以一直枚舉到 [rank[1],rank[1]+m]..所以先通過枚舉得到能夠交換的點。
。然後就是題目的意思了。
。
。
我理解的優惠相當於是分解。
。。比方假設得到1號物品須要得到2號物品和8000金幣。不就相當於1號到2號號為單向路勁,權值為8000.。
。求各個點到1號點的最短路加上這個點的價值。。
如圖所看到的。
。。
1(10000)---------->2(1000)--------->4(50)
| 8000 200 |
|--------------------->3(3000)----------|
5000 200
繪圖之後一目了然。。。
然後運用dijkstra解決。
。。
。。
。。
希望各位指正我的想法。。
代碼例如以下:
#include<cstdio> #include<cstring> #define INF 0x3f3f3f3f const int maxn=100+10; int m,n; int vis[maxn],dis[maxn],e[maxn][maxn]; int withtin[maxn],value[maxn],ranki[maxn]; int dijkstra() { int tmp,now,i,j; memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); dis[1]=0; for(i=1;i<=n;i++) { tmp=INF; for(j=1;j<=n;j++) { if(!vis[j]&&withtin[j]&&dis[j]<tmp) { tmp=dis[j]; now=j; } } vis[now]=1; for(j=1;j<=n;j++) { if(!vis[j]&&withtin[j]&&dis[j]>dis[now]+e[now][j]) dis[j]=dis[now]+e[now][j]; } } tmp=INF; for(i=1;i<=n;i++) { if(dis[i]+value[i]<tmp) tmp=dis[i]+value[i]; } return tmp; } int main() { int i,j,t,cost; int p,l,x,val,min_cost; while(scanf("%d%d",&m,&n)!=EOF) { memset(e,0x3f,sizeof(e)); for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(i==j) e[i][j]=0; } for(i=1;i<=n;i++) { scanf("%d%d%d",&value[i],&ranki[i],&x); for(j=1;j<=x;j++) { scanf("%d%d",&t,&val); e[i][t]=val; } } min_cost=INF; for(i=0;i<=m;i++) { memset(withtin,0,sizeof(withtin)); for(j=1;j<=n;j++) { if(ranki[j]>=ranki[1]-m+i&&ranki[j]<=ranki[1]+i) withtin[j]=1; } cost=dijkstra(); if(cost<min_cost) min_cost=cost; } printf("%d\n",min_cost); } }
poj1062昂貴的聘禮