1. 程式人生 > >NYOJ 203 三國誌(Dijkstra+貪心)

NYOJ 203 三國誌(Dijkstra+貪心)

tom -i pro std scan ins onos () jks

三國誌

時間限制:3000 ms | 內存限制:65535 KB 難度:5
描寫敘述

《三國誌》是一款非常經典的經營策略類遊戲。我們的小白同學是這款遊戲的忠實玩家。如今他把遊戲簡化一下,地圖上僅僅有他一方勢力,如今他僅僅有一個城池,而他周邊有一些無人占的空城,可是這些空城中有非常多不同數量的同種財寶。

我們的小白同學虎視眈眈的看著這些城池中的財寶。

依照遊戲的規則。他僅僅要指派一名武將攻占這座城池,裏面的財寶就歸他全部了。只是一量攻占這座城池,我們的武將就要留守。不能撤回。由於我們的小白手下有無數的武將,所以他不在乎這些。

從小白的城池派出的武將,每走一公理的距離就要消耗一石的糧食,而他手上的糧食是有限的。如今小白統計出了地圖上城池間的道路,這些道路都是雙向的。他想請你幫忙計算出他能得到 的最多的財寶數量。我們用城池的編號代表城池,規定小白所在的城池為0號城池。其它的城池從1號開始計數。

輸入
本題包括多組數據:
首先,是一個整數T(1<=T<=20),代表數據的組數
然後,以下是T組測試數據。對於每組數據包括三行:
第一行:三個數字S,N,M
(1<=S<=1000000,1<=N<=100,1<=M<=10000)
S代表他手中的糧食(石),N代表城池個數。M代表道路條數。


第二行:包括M個三元組行 Ai,Bi,Ci(1<=A,B<=N,1<=C<=100)。


代表Ai,Bi兩城池間的道路長度為Ci(公裏)。


第三行:包括N個元素,Vi代表第i個城池中的財寶數量。

(1<=V<=100)

輸出
每組輸出各占一行。輸出僅一個整數,表示小白能得到的最大財富值。
例子輸入
2
10 1 1
0 1 3
2
5 2 3
0 1 2 0 2 4 1 2 1
2 3
例子輸出
2
5
Dijkstra+貪心算法!
AC碼:
#include<stdio.h>
#include<string.h>
#define INF 99999999
int G[105][105],visit[105],num[105];
int dist[105],dp[1000005];
int max(int a,int b)
{
	return a>b?

a:b; } int main() { int T,s,n,m,a,b,c,min,i,j,k; scanf("%d",&T); while(T--) { scanf("%d%d%d",&s,&n,&m); for(i=0;i<=n;i++) { for(j=0;j<=n;j++) G[i][j]=INF; } for(i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); if(G[a][b]>c) // WA了非常多次,不知道為什麽要加這個推斷條件 G[a][b]=G[b][a]=c; // 創建鄰接矩陣 } for(i=1;i<=n;i++) scanf("%d",&num[i]); // 每一個城市的財富值 // Dijkstra算法求隨意兩點間的最短路徑 memset(visit,0,sizeof(visit)); for(i=0;i<=n;i++) dist[i]=G[0][i]; dist[0]=0; visit[0]=1; for(i=1;i<=n;i++) { min=INF; k=0; for(j=0;j<=n;j++) { if(!visit[j]&&min>dist[j]) { min=dist[j]; k=j; } } visit[k]=1; for(j=0;j<=n;j++) { if(!visit[j]&&dist[j]>dist[k]+G[k][j]) dist[j]=dist[k]+G[k][j]; } }// 最短路徑求解完成 // 貪心算法求得最大財富值 memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) { for(j=s;j>=dist[i];j--) { dp[j]=max(dp[j],dp[j-dist[i]]+num[i]); } } printf("%d\n",dp[s]); } return 0; }



NYOJ 203 三國誌(Dijkstra+貪心)