Google code jam 2008 R1A - Milkshakes

这是Google code jam 2008 R1A的第二道题,关于如何最大限度顾客需求的问题。这可以归类为满足性问题,它是一个NP-完全问题。然而这道题有自己的特征,可以根据题目给定的约束条件,采用比较简单的算法就能得出结果。最后给出源码。

Problem

You own a milkshake shop. There are N different flavors that you can prepare, and each flavor can be prepared "malted" or "unmalted". So, you can make 2N different types of milkshakes.

Each of your customers has a set of milkshake types that they like, and they will be satisfied if you have at least one of those types prepared. At most one of the types a customer likes will be a "malted" flavor.

You want to make N batches of milkshakes, so that:

  • There is exactly one batch for each flavor of milkshake, and it is either malted or unmalted.
  • For each customer, you make at least one milkshake type that they like.
  • The minimum possible number of batches are malted.

Find whether it is possible to satisfy all your customers given these constraints, and if it is, what milkshake types you should make.

If it is possible to satisfy all your customers, there will be only one answer which minimizes the number of malted batches.

Input

  • One line containing an integer C, the number of test cases in the input file.

For each test case, there will be:

  • One line containing the integer N, the number of milkshake flavors.
  • One line containing the integer M, the number of customers.
  • M lines, one for each customer, each containing:
    • An integer T >= 1, the number of milkshake types the customer likes, followed by
    • T pairs of integers "X Y", one for each type the customer likes, where X is the milkshake flavor between 1 and N inclusive, and Y is either 0 to indicate unmalted, or 1 to indicated malted. Note that:
      • No pair will occur more than once for a single customer.
      • Each customer will have at least one flavor that they like (T >= 1).
      • Each customer will like at most one malted flavor. (At most one pair for each customer has Y = 1).
    All of these numbers are separated by single spaces.

Output

  • C lines, one for each test case in the order they occur in the input file, each containing the string "Case #X: " where X is the number of the test case, starting from 1, followed by:
    • The string "IMPOSSIBLE", if the customers' preferences cannot be satisfied; OR
    • N space-separated integers, one for each flavor from 1 to N, which are 0 if the corresponding flavor should be prepared unmalted, and 1 if it should be malted.

Limits

Small dataset

C = 100
1 <= N <= 10
1 <= M <= 100

Large dataset

C = 5
1 <= N <= 2000
1 <= M <= 2000

The sum of all the T values for the customers in a test case will not exceed 3000.

Sample


Input
 

Output
 
2
5
3
1 1 1
2 1 0 2 0
1 5 0
1
2
1 1 0
1 1 1
Case #1: 1 0 0 0 0
Case #2: IMPOSSIBLE

In the first case, you must make flavor #1 malted, to satisfy the first customer. Every other flavor can be unmalted. The second customer is satisfied by getting flavor #2 unmalted, and the third customer is satisfied by getting flavor #5 unmalted.

In the second case, there is only one flavor. One of your customers wants it malted and one wants it unmalted. You cannot satisfy them both.

Analysis
On the surface, this problem appears to require solving the classic problem "Satisfiability," the canonical example of an NP-complete problem. The customers represent clauses, the milkshake flavors represent variables, and malted and unmalted flavors represent whether the variable is negated.

We are not evil enough to have chosen a problem that hard! The restriction that makes this problem easier is that the customers can only like at most one malted flavor (or equivalently, the clauses can only have at most one negated variable.)

Using the following steps, we can quickly find whether a solution exists, and if so, what the solution is.

  1. Start with every flavor unmalted and consider the customers one by one.
  2. If there is an unsatisfied customer who only likes unmalted flavors, and all those flavors have been made malted, then no solution is possible.
  3. If there is an unsatisfied customer who has one favorite malted flavor, then we must make that flavor malted. We do this, then go back to step 2.
  4. If there are no unsatisfied customers, then we already have a valid solution and can leave the remaining flavors unmalted.

Notice that whenever we made a flavor malted, we were forced to do so. Therefore, the solution we got must have the minimum possible number of malted flavors.

With clever data structures, the above algorithm can be implemented to run in linear time.

More information:

The Satisfiability problem - Horn clauses


Source Code
#include  < iostream >

using   namespace  std;

#define  Rep(i,n) for (int i(0),_n(n); i<_n; ++i)

ExpandedBlockStart.gifContractedBlock.gif
struct  Flavor {
    
int X;
    
char Y;
}
;

ExpandedBlockStart.gifContractedBlock.gif
struct  Customer {
    
int T;
    Flavor
* F;
ExpandedSubBlockStart.gifContractedSubBlock.gif    Customer() 
{
        F 
= NULL;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
~Customer() {
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if(NULL!=F) {
            delete[] F;
            F 
= NULL;
        }

    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
void Init(int t) {
        T 
= t;
        F 
= new Flavor[T];
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
void SetFlavor(int i, int X, int Y) {
        F[i].X 
= X;
        F[i].Y 
= Y;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
int GetFlavorX(int i) {
        
return F[i].X;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
int GetFlavorY(int i) {
        
return F[i].Y;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
bool IsSatisfied() {
        
return T==0;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
void Satisfy() {
        T
=0;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if(NULL!=F) {
            delete[] F;
            F 
= NULL;
        }

    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
bool IsSatisfing(int i, int *f) {
        
return f[F[i].X]==F[i].Y;
    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
void SetMalted(int i, int *f) {
        f[F[i].X] 
= 1;
    }

}
;

int  main()
ExpandedBlockStart.gifContractedBlock.gif
{
    
int C;
    FILE 
*fp = fopen("A.out""w");
    scanf(
"%d"&C);
ExpandedSubBlockStart.gifContractedSubBlock.gif    Rep(c, C) 
{
        
int N;
        scanf(
"%d"&N);
        
int* f = new int[N+1];
ExpandedSubBlockStart.gifContractedSubBlock.gif        Rep(i ,N
+1{
            f[i]
=0;
        }

        
int M;
        scanf(
"%d"&M);
        Customer
* customer = new Customer[M];
ExpandedSubBlockStart.gifContractedSubBlock.gif        Rep(m, M) 
{
            
int T;
            scanf(
"%d"&T);
            customer[m].Init(T);
ExpandedSubBlockStart.gifContractedSubBlock.gif            Rep(t, T) 
{
                
int X, Y;
                scanf(
"%d%d"&X,&Y);
                customer[m].SetFlavor(t,X,Y);
            }

        }

        
bool findSolution = true;
        
int m = 0;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
while(m<M) {
ExpandedSubBlockStart.gifContractedSubBlock.gif            
if(customer[m].IsSatisfied()) {
                m
++;
                
continue;
            }

            
bool malted = false;
            
int idx;
            
bool satisfied = false;
ExpandedSubBlockStart.gifContractedSubBlock.gif            Rep(t, customer[m].T) 
{
ExpandedSubBlockStart.gifContractedSubBlock.gif                
if(customer[m].GetFlavorY(t)==1{
                    malted 
= true;
                    idx 
= t;
                }

ExpandedSubBlockStart.gifContractedSubBlock.gif                
if(customer[m].IsSatisfing(t,f)) {
                    satisfied 
= true;
                }

            }

ExpandedSubBlockStart.gifContractedSubBlock.gif            
if(!satisfied) {
ExpandedSubBlockStart.gifContractedSubBlock.gif                
if(malted) {
                    customer[m].SetMalted(idx,f);
                    customer[m].Satisfy();
                    m
=0;
ExpandedSubBlockStart.gifContractedSubBlock.gif                }
 else {
                    findSolution 
= false;
                    
break;
                }

ExpandedSubBlockStart.gifContractedSubBlock.gif            }
 else {
                m
++;
            }

        }

        fprintf(fp,
"Case #%d: ", c+1);
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if(findSolution) {
ExpandedSubBlockStart.gifContractedSubBlock.gif            Rep(i ,N) 
{
                fprintf(fp,
"%d ", f[i+1]);
            }

            fprintf(fp,
"\n");
ExpandedSubBlockStart.gifContractedSubBlock.gif        }
 else {
            fprintf(fp,
"IMPOSSIBLE\n");
        }

        delete[] customer;
        delete[] f;

    }

    fclose(fp);
}

转载于:https://www.cnblogs.com/clive/archive/2009/08/13/Google_code_jam_2008_R1A_Milkshakes.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值