题目不太好读懂,就是先给你一个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