Description
Unfortunately the problem is a bit more complicated: with some pizzas Alberto gives out discount coupons for getting another pizza cheaper and even worse, those coupons can be combined. The pizzas have to be bought one after the other, and it is not possible to use a coupon to get a discount retrospectively for a pizza which has already been bought. Can you help Bob to become the first to solve this task and to get a pizza for free?
Input
Output
Sample Input
1 80 30 0 2 200 100 1 2 50 200 100 0 5 100 100 2 3 50 2 50 100 100 1 4 50 100 100 1 2 40 600 600 1 5 10 1000 10 1 1 50 0
Sample Output
2.6667 1.5000 0.5333
题意很简单,求买的pizza的总价钱除于总面积的最小值,因为面积固定而价钱可以通过过程调整,很明显是状压DP的套路但是在数据的存储上确实需要很大技巧,,,
因为买了一个pizza就可以把它的优惠卷直接转换成比例累积存储下来,如果还按数量去存储的话,很会很麻烦,只要存储没问题,就只是类似于TSP的用出现过的去更新没出现过的并保留最小值得套路了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int N = (1<<15)+10;
double dp[N], q[N][20], p[N], a[N];
int main()
{
int n, num;
while(scanf("%d", &n),n)
{
for(int i=0;i<(1<<n);i++)
{
dp[i]=100000000;
for(int j=0;j<=n;j++)
{
q[i][j]=1.0;
}
}
for(int i=0;i<n;i++)
{
scanf("%lf %lf",&p[i], &a[i]);
scanf("%d", &num);
for(int j=1;j<=num;j++)
{
int x;
double y;
scanf("%d %lf",&x, &y);
q[i][x-1]=q[i][x-1]*(100-y)*0.01;
}
}
double ans=100000000;
dp[0]=0;
for(int i=0;i<(1<<n);i++)
{
if(dp[0]==100000000)
continue;
double area=0;
for(int j=0;j<n;j++)
{
if(i&(1<<j))
area+=a[j];
else
{
double cost=p[j];
for(int k=0;k<n;k++)
{
if(i&(1<<k))
cost*=q[k][j];
}
int state=i|(1<<j);
if(dp[state]>dp[i]+cost)
dp[state]=dp[i]+cost;
}
}
if(i)
ans=min(ans,dp[i]/area);
}
printf("%.4f\n",ans);
}
return 0;
}