柱爷与三叉戟不得不说的故事
Time Limit: 500/500MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
在喵蛤蛤城,人人都知晓柱爷有一把传奇武器三叉戟
.据传,这是一位在
772002
年前陨落的强大守护者F91曾经使用过的12级灵能武器,拥有毁天灭地的力量
但只有很少人知道当柱爷获得三叉戟时,三叉戟的力量已经消失殆尽.为了能修复三叉戟的力量,柱爷苦心专研古籍,发现只有找到最神秘的 15 种元素,将元素的力量重新注入到三叉戟中,三叉戟就能恢复到原来的力量,于是柱爷踏上了寻找神秘元素的旅行.
柱爷首先发现 15 个由卿学姐掌控的地牢,里面正好有 15 种对应元素.冷静的柱爷没有贸然行动,经过一番详细的打听,柱爷得知了第 i 种元素需要 Di 的精力去获得;与此同时,柱爷还发现了由白学潘看守的 N 个洞穴,第 i 个洞穴中有 Ai 个不同的元素,分别是 B1,B2,...,BAi ,需要 Ci 的精力去获得.
同种元素不得拥有多个,不然元素之间会产生强大的斥力,会发生爆炸;不能攻下一个洞穴后,留有元素不拿走,元素可能会辐射,伤害喵哈哈村的大爷......
但是柱爷岂是凡人?柱爷修复三叉戟时花费的总是最小的精力!
那么这个最小的花费是多少呢?
Input
第一行包括 15 个正整数,第 i 个数表示 Di .
第二行包括一个整数表示 N .
接下来 N 行,每行有一个整数表示 Ai ,后面紧接着 Ai 个不同的正整数,最后又一个正整数 Ci 表示需要花费的精力.
数据保证:
-
0≤N≤10000
-
1≤Di≤20000
-
0≤Ai≤5
-
1≤Ci≤2000000
Output
输出一个整数 ans :
表示至少花 ans 的精力去修复三叉戟.
Sample input and output
Sample Input | Sample Output |
---|---|
9599 11186 3513 3112 19106 1171 4254 4786 11880 19550 4793 17049 10779 11096 9713 5 4 10 1 8 11 1212645 3 14 9 15 1655560 3 7 3 14 1161262 5 13 5 9 2 11 710512 0 980331 | 141587 |
Source
题解:这是一道状压dp题目,看到15种元素,可以想到状压到2^15次方显然是可以的,然后就是枚举子集找最小值了,一开始我手写了一个暴力枚举,但是T了,后来在一篇博客中看到了这种枚举方式for(int j=i;j;j=(j-1)&i),dp[i]=min(dp[i],dp[j]+dp[j^i]);改了之后就过了。
代码如下:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL dp[66000];
LL bit1[20];
LL b15;
int main()
{
LL b15=2;
bit1[1]=2;
bit1[0]=1;
fill(dp,dp+66000,1000000000000);
for(int i=2;i<=15;i++){
bit1[i]=bit1[i-1]*2;
b15+=bit1[i];
}
for(int i=1;i<=15;i++)
scanf("%lld",&dp[bit1[i]]);
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int nod;
scanf("%d",&nod);
LL nn=0;
for(int j=0;j<nod;j++)
{
//cout<<1<<endl;
LL val;
scanf("%lld",&val);
nn+=bit1[val];
}
//cout<<1<<endl;
LL vl;
scanf("%lld",&vl);
dp[nn]=min(dp[nn],vl);
//cout<<dp[nn]<<endl;
}
for(int i=1;i<=b15;i++)
for(int j=i;j;j=(j-1)&i)
{
dp[i]=min(dp[i],dp[j]+dp[j^i]);
//cout<<dp[i]<<endl;
}
cout<<dp[b15]<<endl;
return 0;
}