하늘에서 떨어지다 피자

4394 단어 DP 동적 계획
원제:zjnu 1192
제목:
피자 한 가지를 사면 다른 피자 쿠폰을 받을 수 있는데, 단위 면적의 피자를 어떻게 팔면 가격이 가장 적게 팔릴 수 있냐고 묻는다(한 개 두 개 사면 마음대로 살 수 있다)
해결:
만약 dp문제가 순서문제를 풀었다면, 돌려서 풀기가 매우 어려울 것이다
올바른 방법은 매거 상태로 이전의 상태에서 옮겨오는 것이다.그러나 누가 먼저 사고 누가 사야 할지 생각하면 잘못된 길을 걷게 된다
dp[i]는 상태가 i일 때 최소 비용을 표시한다.eg:피자 5개==29(11101)는 피자 1,3,4,5종을 샀을 때의 상태를 표시하고 상태 이동 방정식은 dp[i]=min(dp[i],dp[i-(1<이다.
코드:
#include
#include
#include
#include
#include
using namespace std;

double ans;
int n,k;
double p[20],s[20];
double c[20][20];

double dp[1<<16],siz[1<<16];

int main(){
    while(scanf("%d",&n),n){
        ans=2.14e9;
        memset(c,0,sizeof(c));
        memset(siz,0,sizeof(siz));
        memset(dp,127,sizeof(dp));
        for(int i=1;i<=n;i++){
            scanf("%lf%lf%d",p+i,s+i,&k);
            while(k--){
                int a,b;
                scanf("%d%d",&a,&b);
                c[i][a]=(100-b)*1.0/100.0;
            }
        }
        dp[0]=0;
        for(int i=1;i1<for(int j=1;j<=n;j++){
                int f=1;
                if((i&(1<1)))==0)continue;
                double w=p[j];
                for(int k=1;k<=n;k++){
                    if((i&(1<1)))==0)continue;
                    if(c[k][j]<1e-8)continue;
                    w*=c[k][j];
                }
                dp[i]=min(dp[i-(1<1))]+w,dp[i]);
                siz[i]=siz[i-(1<1))]+s[j];
            }
            //printf("dp[%d] is %.1lf,size is %.1f
",i,dp[i],siz[i]);
ans=min(ans,dp[i]/siz[i]); } printf("%.4lf
"
,ans); } }

좋은 웹페이지 즐겨찾기