poj 1724

這題需要剪枝

到達某個城市c的路徑有許多條,可能會有一些花的錢相同但路徑不同的路線。

也就是說 我們走到城市c只花了m1的錢,從另一條路走到c卻花了多餘m1的錢,

那麼這條路沒有必要繼續走下去,要麼到不了,要麼路徑長度和之前的路是一樣的,

總之不會小於那個花錢少的路線

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int K, N, R;

struct Road {
	int end, length, cost;
	
};

vector<vector<Road> > city(105);
const int INF = 1 << 30;
int ans;
int totalLen;
int totalcost;
bool vis[105];
int midL[105][10005];//midL[i][j] 表示 到達i城市時花費路費爲j所走的最短路徑

void dfs(int n)
{
	if (n == N)
	{
		ans = min(ans, totalLen);
		return;
	}
	int size = city[n].size();
	for (int i = 0; i < size; ++i)
	{
		int e = city[n][i].end;
		if (!vis[e])
		{
			int cost = totalcost + city[n][i].cost;
			if (cost > K)
				continue;
			int len = totalLen + city[n][i].length;
			if (len >= ans || len >= midL[e][cost])
				continue;
			totalcost = cost;
			totalLen = len;
			midL[e][cost] = len;
			vis[e] = true;
			dfs(e);
			vis[e] = false;
			totalLen -= city[n][i].length;
			totalcost -= city[n][i].cost;
		}
	}

}

int main()
{
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	ios::sync_with_stdio(false);
	int s;
	Road t;
	while (cin >> K >> N >> R)
	{
		//memset(midL, INF, sizeof(midL));
		for (int i = 0; i < 105; ++i)
			for (int j = 0; j < 10005; ++j)
				midL[i][j] = INF;
		memset(vis, false, sizeof(vis));
		ans = INF;
		totalcost = 0;
		totalLen = 0;
		vis[1] = true;
		for (int i = 0; i < R; ++i)
		{
			cin >> s >> t.end >> t.length >> t.cost;
			if (s != t.end)
			{
				city[s].push_back(t);
			}
		}
		dfs(1);
		if (ans != INF)
			cout << ans << endl;
		else
			cout << -1 << endl;
	}
	return 0;
}


發佈了55 篇原創文章 · 獲贊 11 · 訪問量 7830
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章