题目不太好读懂,就是先给你一个n代表要从n个物品中买东西,然后告诉你这n个东西的单价,在给你m个集合的情况,就是每个结合中有x件物品,他们合起来买的价格是k。这x件物品依次是:p1……px。之后给你一个kk,表示你要买的物品的编号。让你求出来如何花费最少的钱买到要求的序列。
20,可以状压啊,注意一开始的时候先把单价的状态处理出来。。。之后就是水题了啊。
input | output |
---|---|
4 10 11 12 13 3 17 2 1 3 25 3 2 3 4 15 2 3 4 3 1 3 4 |
25 |
#include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #include <iomanip> #include <stdio.h> #include <string> #include <queue> #include <cmath> #include <stack> #include <map> #include <set> #define eps 1e-8 #define M 1000100 #define LL __int64 //#define LL long long #define INF 0x3f3f3f #define PI 3.1415926535898 const int maxn = 1010; using namespace std; int dp[1<<22]; int num[maxn]; int f[maxn]; int st[maxn]; int n; void dfs(int x, int y, int z) { if(x == n) { dp[y] = z; return; } dfs(x+1, y, z); dfs(x+1, y|(1<<x), z+num[x]); } int main() { while(~scanf("%d",&n)) { for(int i = 0; i < (1<<n); i++) dp[i] = INF; for(int i = 0; i < n; i++) scanf("%d",&num[i]); dfs(0, 0, 0); int m; scanf("%d",&m); for(int i = 0; i < m; i++) { scanf("%d",&f[i]); int x; scanf("%d",&x); int sum = 0; int tmx; for(int j = 0; j < x; j++) { scanf("%d",&tmx); sum |= (1<<(tmx-1)); } st[i] = sum; } int kk; scanf("%d",&kk); int ans = 0; int p; for(int i = 0; i < kk; i++) { scanf("%d", &p); ans |= (1<<(p-1)); } int Min = INF; for(int i = 0; i < (1<<n); i++) { if((i&ans) == ans) Min = min(Min, dp[i]); for(int j = 0; j < m; j++) dp[i|st[j]] = min(dp[i|st[j]], dp[i]+f[j]); } printf("%d\n",Min); } return 0; }
URAL 1326. Bottle Taps(简单的状压dp)
原文:http://blog.csdn.net/xu12110501127/article/details/40352313