程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 九度筆記之 1420:Jobdu MM分水果

九度筆記之 1420:Jobdu MM分水果

編輯:C++入門知識

題目1420:Jobdu MM分水果

 

題目描述:
Jobdu團隊有倆PPMM,這倆MM干啥都想一樣。一天,富強公司給團隊贊助了一批水果,胡老板就把水果派發給了這倆MM,由她們自行分配。每個水果都有一個重量,你能告訴她們怎麼分才使得分得的重量差值最小嗎?

輸入:
 輸入有多組數據,每組數據第一行輸入水果個數n(1<=n<=100),接下來一行輸入n個重量wi(0<=wi<=10^5)。

輸出:
對每組輸入輸出一行,輸出可以得到的最小差值。

樣例輸入:
510 20 30 10 10

 

 

算法分析
     這道題和 題目1358:程博的平均主義  可以看作同一道題。

     我們利用動態規劃來做。假設所有水果總重為sum, 那麼其中一個人所能分得的水果重量w范圍一定在 0 - sum/2之間,

     也許有人會問 sum為奇數時,w范圍應該在0 - (sum/2+1)之間,當一個人分得sum/2+1時,另外一個人分得的必定是sum/2,這和我們求質數時,測試范圍從 2到sqrt(n)一樣。

     我們的問題就轉化為  一個人所分得的重量w從 sum/2 到0  哪個重量可以實現。

     我們當給一個人什麼水果都不分的話,就可以實現0.  即 dp[0] = true;

     當我們選擇第i個水果時,該水果重量為num[i], 我們判斷在第i個水果分配給這個人之前 dp[w]是否為true,或者dp[w-num[j]]是否為true;

            如果從前i-1個水果中挑出某幾個可以組成重量w,那麼dp[w] = true;

            如果從前i-1個水果中挑出某幾個可以組成重量w-num[i], 那麼加上第i個水果的重量就可以組成w,所以

 

 

dp[j] = dp[j]||dp[j-num[i]]; 
        dp[j] = dp[j]||dp[j-num[i]];

      在更新dp的時候一定注意是要從sum/2 到 num[i], 這樣才能保證每個水果出現了0次或1次。

      如果dp從num[i]到sum/2更新,那麼 dp[j-num[i]] 就可能是已經放入第i個水果的結果。類似的如

      題目1455:珍惜現在,感恩生活  (每個元素數量有有限多個的,可以轉為多個單獨的)

      題目1434:今年暑假不AC  

      題目1499:項目安排 

      對於每個元素數量無限的,dp從num[i] 到最多遞增更新

      題目1455:珍惜現在,感恩生活

     

源程序

//============================================================================
// Name        : judo1358.cpp
// Author      : wdy
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
//similar to   judo1358
#include <iostream>
int num[101];
using namespace std;
 
void allocate(int n){
    int sum=0;
    for(int i = 0;i<n;i++){
        std::cin>>num[i];
        sum+=num[i];
    }
     
    int maxPercent = sum>>1;
    bool *dp = new bool[maxPercent+1];
    for(int i = 1;i<maxPercent+1;i++)
        dp[i] = false;
    dp[0] = true;
    for(int i = 0;i<n; i++){
        for(int j = maxPercent; j>=num[i]; j--)
            dp[j] = dp[j]||dp[j-num[i]];
    }
    for(int i = maxPercent;i>0;i--){
        if(dp[i]){
            std::cout<< sum-2*i<<std::endl;
            break;
        }
    }
}
 
void judo(){
    int n;
    while(std::cin>>n){
        allocate(n);
    }
}
int main() {
    judo();
    return 0;
}
/**************************************************************
    Problem: 1420
    User: KES
    Language: C++
    Result: Accepted
    Time:770 ms
    Memory:3888 kb
****************************************************************/

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved