Mr. Panda and Crystal ( 最短路+完全揹包 )
阿新 • • 發佈:2018-12-13
題意
島上有n種寶石,有的寶石可以用魔力值合成,有的寶石不可以用魔力值合成。還有k種配方,即由幾種寶石合成另一種。每一種寶石都有一個售價。現在,Panda有m的魔力值,問Panda得到的寶石最多能賣出多少錢。
思路
可以通過配方用消耗魔力值低的寶石去合成消耗魔力值低或者不能夠用魔力值合成但是售價高的寶石,只要能夠知道每個寶石最少需要多少魔力值合成,就可以將模型轉化為物品重量為最低魔力值,價值為寶石售價,容量為m的完全揹包。比賽的時候開這個題開的太晚了,只剩不到一個小時,所以沒想清楚關於計算每個寶石合成所需要的“最低魔力值”如何計算,曾經想過跑最短路,但是當時沒想清楚怎麼建圖。dijkstra處理出來之後,就是非常水的完全揹包了。
注意每個寶石消耗的魔力值c[i]不能夠初始化為INF,因為有的寶石可能最終也無法由任何方式合成,因此RE了好幾次。其實直接把一開始無法用魔力之合成的寶石c[i]定義為m+1就可以了。
AC程式碼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
using namespace std;
const int maxn = 210;
const int INF = 0x3f3f3f3f ;
int c[maxn], w[maxn];
int dp[10010];
vector<int> g[maxn];
bool vis[maxn];
int m, n, k;
struct node {
int to, cost;
bool operator < (const node n_) const {
return cost > n_.cost;
}
};
priority_queue<node> que;
struct node2 {
int goal;
vector<pair< int, int> > vec;
}e[maxn];
void check() {
puts("------------\n");
for(int i = 1; i <= n; i++)
printf("%d %d\n", i, c[i]);
puts("\n------------");
}
int getsum(node2& nd) {
int sum = 0;
for(int i = 0; i < nd.vec.size(); i++) {
sum += nd.vec[i].second * c[nd.vec[i].first];
}
return sum;
}
void dijkstra() {
int u, newcost;
while(!que.empty()) {
node nd = que.top();
que.pop();
u = nd.to;
if(vis[u]) continue;
vis[u] = true;
for(int i = 0; i < (int)g[u].size(); i++) {
node2& nd2 = e[g[u][i]];
newcost = getsum(nd2);
if(newcost < c[nd2.goal]) {
c[nd2.goal] = newcost;
que.push((node){nd2.goal, c[nd2.goal]});
}
}
}
}
void init() {
memset(vis, 0, sizeof vis);
memset(dp, 0, sizeof dp);
}
int main()
{
int T;
int kase = 0;
scanf("%d", &T);
while(T--) {
init();
scanf("%d%d%d", &m, &n, &k);
int flag;
for(int i = 1; i <= n; i++) {
g[i].clear();
scanf("%d", &flag);
if(flag) {
scanf("%d", &c[i]);
que.push((node){i, c[i]});
}
else {
c[i] = m+1;
}
scanf("%d", &w[i]);
}
int sum_, type_, num_;
for(int i = 0; i < k; i++) {
scanf("%d%d", &e[i].goal, &sum_);
e[i].vec.clear();
for(int j = 0; j < sum_; j++) {
scanf("%d%d", &type_, &num_);
e[i].vec.push_back(make_pair(type_, num_));
g[type_].push_back(i);
}
}
dijkstra();
//check();
for(int i = 1; i <= n; i++) {
for(int v = c[i]; v <= m; v++) {
dp[v] = max(dp[v], dp[v-c[i]]+w[i]);
}
}
printf("Case #%d: %d\n", ++kase, dp[m]);
}
return 0;
}