我的北大ACM POJ 1014解答

[原创]我的北大ACM POJ 1014解答

动态规划DP的题,没看提示之前还真不知怎么写。。。

Source Code

Problem: 1014 User: absolute
Memory: 256K Time: 16MS
Language: C++ Result: Accepted
  • Source Code
    #include <stdio.h>
    
    void POJ1014();
    
    int main()
    
    {
    
    	POJ1014();
    
    	return 0;
    
    }
    
    //查找是否可以通过组合凑出价值为sum
    
    bool Divided(int* nums,int sum)
    
    {
    
    	//hasvalue存储通过组合是否可以达到相应价值
    
    	bool hasvalue[60001]={0};
    
    	hasvalue[0] = true;
    
    	//maxsum存储目前组合达到的最大价值
    
    	int i,maxsum=0,temp,j,k;
    
            //dp法分6个阶段,每个阶段都使用上一段可能凑出的价值加上当前阶段可能的价值
    
             //最后即可得出所有可能凑出的价值
    
    	for(i=1;i<7;i++)
    
    	{
    
    		if(nums[i-1]!=0)
    
    		{
    
    			for(j=maxsum;j>=0;j--)
    
    			{
    
    				if(hasvalue[j])
    
    				{
    
    				        temp = j;
    
                                            //这个很重要,如果首个已经达到了,则后面的可以不用判断
    
                                                 //因为可以从该达到的值加temp达到,而由于该值已经达到,说明已经判断过
    
                                                 //它后面加temp的值
    
                                                 // value+temp, value+temp+temp->[value+temp],[value+temp]+temp
    
                                            if((temp+i>sum)||hasvalue[temp+i])
    
                                                continue;
    
    					for(k=0;k<nums[i-1];k++)
    
    					{
    
    						temp += i;
    
                                                    if(temp>sum)
    
                                                        break;
    
    						hasvalue[temp] = true;
    
    						if(temp==sum)
    
    							return true;
    
    					}
    
    					if(temp>maxsum)
    
    						maxsum=temp;
    
    					if(maxsum>sum)
    
    						maxsum=sum;
    
                                     }
    
    			}
    
    		}
    
    	}
    
    	if(hasvalue[sum])
    
    		return true;
    
    	else
    
    		return false;
    
    }
    
    void POJ1014()
    
    {
    
    	int ncase=0;
    
    	while(1)
    
    	{
    
    		ncase++;
    
    		int sum=0,i;
    
    		int nums[6]={0};
    
                    bool alleven = true;
    
    		for(i=0;i<6;i++)
    
    		{
    
    			scanf("%d",nums+i);
    
    			sum += nums[i]*(i+1);
    
                            if(nums[i]%2!=0)
    
                                alleven=false;
    
    		}
    
    		if(sum==0)
    
    			return;
    
    		printf("Collection #%d:\n",ncase);
    
                   //所有价值的都是偶数个则可以分
    
                     if(alleven)
    
                   {
    
                       printf("Can be divided.\n");
    
                       continue;
    
                   }
    
                    //价值相加总和为奇数则不可分
    
    		if(sum%2!=0)
    
    			printf("Can't be divided.\n");
    
    		else
    
    		{
    
    			if(Divided(nums,sum/2))
    
    			{
    
    				printf("Can be divided.\n");
    
    			}
    
    			else
    
    				printf("Can't be divided.\n");
    
    		}
    
                    printf("\n");
    
    
    
    	}
    
    }

你可能感兴趣的:(ACM)