题意:

出一些独立的陆地,每片陆地上有非常多怪物。杀掉每一个怪物都须要一定的时间,并能获得一定的金钱。给出指定的金钱m, 求最少要多少时间能够得到m金钱,仅能选择一个陆地进行杀怪。

题解:

这题,假设无论数据范围,非常easy想到对每片陆地求一次0-1背包(dp(i, j) = min(dp(i-1, j), dp[i-1, j-money] + time), i 为金钱)。然后在全部陆地中找出最少的时间即为答案,可是这题的数据范围太大金钱m可达到1e9, 所以不能单纯的直接用数组模拟,考虑第i个怪物,要更新第i个怪物。仅仅须要知道两个状态,那就是dp[i-1][j],
和dp[i-1][j-money]。 所以。我们仅仅须要保存第i-1个怪物的所有合法状态,就能更新第i个怪物的状态。 所以我们能够考虑使用两个优先队列来维护上一轮的状态和这一轮的状态。就能找到答案了。首先,将两个队列都依照money从大到小。time从小到大的顺序排列,每次把q1所有出队列更新下一个状态,并把两个状态都放入q2中,然后从q2中选择最优解再拷贝到q1中,最后更新ans就可以。

代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef vector<int>::iterator Pointer;
const int maxn = 60;
const int inf = 1e9;
vector<int> group[maxn];
vector<int> mp[maxn];
int n, m, gcnt;
struct node
{
LL tm, val;
node() {}
node(LL tm, LL val) : tm(tm), val(val) {}
bool operator < (const node& tmp) const
{
return val < tmp.val || (val == tmp.val && tm > tmp.tm);
}
}arr[maxn], now, nxt;
void init()
{
for (int i = 0; i < maxn; ++i) group[i].clear(), mp[i].clear();
}
bool vis[maxn];
void dfs(int u)
{
group[gcnt].push_back(u);
vis[u] = true;
for (Pointer it = mp[u].begin(); it != mp[u].end(); ++it)
{
int v = *it;
if (!vis[v])
{
dfs(v);
}
}
}
void divide_group()
{
memset(vis, false, sizeof vis);
gcnt = 0;
for (int i = 1; i <= n; i++)
{
if (!vis[i])
{
dfs(i);
gcnt++;
}
}
} priority_queue<node> q1, q2;
inline void clear_queue()
{
while (!q1.empty())
{
q1.pop();
}
while (!q2.empty())
{
q2.pop();
}
}
LL mint;
void zeroOnePack(int team)
{
for (Pointer it = group[team].begin(); it != group[team].end(); ++it)
{
int v = *it;
while (!q1.empty())
{
now = q1.top(), q1.pop();
q2.push(now);
nxt = node(now.tm+arr[v].tm, now.val+arr[v].val);
if (nxt.val >= m && nxt.tm < mint)
{
mint = nxt.tm; continue;
}
if (nxt.tm >= mint) continue;
q2.push(nxt);
}
LL pre = inf;
while (!q2.empty())
{
node tmp = q2.top(); q2.pop();
if (tmp.tm < pre)
{
pre = tmp.tm;
q1.push(tmp);
}
}
}
}
LL solve()
{
mint = inf; for (int i = 0; i < gcnt; i++)
{
now = node(0, 0);
clear_queue();
q1.push(now);
zeroOnePack(i);
} return mint == inf ? -1 : mint;
}
int main()
{
// freopen("/Users/apple/Desktop/in.txt", "r", stdin); int t, kase = 0; scanf("%d", &t); while (t--)
{
scanf("%d%d", &n, &m);
init();
for (int i = 1; i <= n; i++)
{
int k; scanf("%lld%lld%d", &arr[i].tm, &arr[i].val, &k);
for (int j = 0; j < k; j++)
{
int v; scanf("%d", &v);
mp[i].push_back(v);
}
}
divide_group();
LL ans = solve();
printf("Case %d: ", ++kase);
if (ans == -1)
{
printf("Poor Magina, you can't save the world all the time!\n");
}
else
{
printf("%lld\n", ans);
}
} return 0;
}

最新文章

  1. 用github来展示你的前端页面吧
  2. Error invoking SqlProvider method (com.github.abel533.mapper.MapperProvider.dynamicSQL). Cause: java.lang.InstantiationException: com.github.abel533.mapper.MapperProvider
  3. 【荐】如何正确理解PHP之include,include_once,require,require_once等包含作用域
  4. linux环境下安装jdk
  5. 7z命令行工具
  6. 在C++中调用DLL中的函数
  7. HttpWebRequest中的KeepAlive
  8. Python偏函数实例
  9. Zepto源码笔记(三)
  10. 8、Khala的设备间管理+通信
  11. [NOIP1999提高] CODEVS 1047 邮票面值设计(dfs+dp)
  12. 一个通用onReady函数的实现
  13. 《深入理解Java虚拟机》学习笔记(二)
  14. Yarn常用命令总结
  15. css 讲浮动,haslayout,BFC的文章
  16. [转]java调用外部程序Runtime.getRuntime().exec
  17. Deep compression code
  18. kettle_Spoon 修改共享DB连接带汉字引发的错误
  19. java将SSL证书导入系统密钥库
  20. &lt;trim&gt;: prefix+prefixOverrides+suffix+suffixOverrides

热门文章

  1. 【洛谷2982】[Usaco2010 Feb]慢下来Slowdown(dfs序+线段树)
  2. [Luogu 1052] noip 05 过河
  3. 342 Power of Four 4的幂
  4. No operations allowed after connection closed--转
  5. MySQL数据库的三大范式定义,作用—------你所期待的最佳答案
  6. jQuery——尺寸位置
  7. (转)Hibernate中的多表操作
  8. 贴一段自动编译java,并混淆编译的代码
  9. Sping bean的作用域
  10. Learning opencv续不足(七)线图像的设计D