Thứ Năm, 23 tháng 2, 2012

Bài toán chia phần thưởng


Cần chia hết m phần thưởng cho n học sinh sắp theo thứ tự từ giỏi trở xuống sao cho mỗi bạn nhận được phần thưởng không ít hơn phần thưởng của bạn xếp sau mình (có thể số phần thưởng = 0), 1<=m,n<= 70. Tính số cách chia phần thưởng.
Cách phát biểu khác của bài toán: Có m phần thưởng được chia cho n học sinh giỏi được xếp hạng thừ 1 đến n. Tính số cách chia phần thưởng sao cho thỏa các điều kiện sau:
  • Số phần thưởng của học sinh hạng i phải lớn hơn hoặc bằng số phần thưởng của học sinh hạng j nếu j>i.
  • Tất cả phần thưởng đều phải được thưởng hết cho học sinh.
Ví dụ: Có 7 phần thưởng chia cho 4 học sinh sẽ có 11 cách chia sau:
baitoanchiaphanthuong Bài toán chia phần thưởng
1. Phương pháp quy hoạch động:
Gọi C[i,j] là số các chia i phần thưởng cho j học sinh, ta có một số nhận xét sau:
  • Có i phần thưởng mà chia cho 0 học sinh thì có 0 cách chia (vì không thỏa điều kiện: Tất cả phần thưởng đều phải được thưởng hết cho học sinh). Vậy với mọi i, C[i,0]=0.
  • Có 0 phần thưởng mà chia cho j học sinh thì có 1 cách chia (không ai có phần thưởng cả). Vậy với mọi j, C[0,j]=1.
  • Nếu số phần thưởng (i) ít hơn số học sinh (j) thì những học sinh thứ i+1 đến j sẽ không có phần thưởng, do đó số cách chia i phần thưởng cho j người sẽ bằng số cách chia i phần thưởng cho i người Vậy với mọi i<j, C[i,j]=C[i,i].
  • Nếu số phần thưởng (i) nhiều hơn hoặc bằng số học sinh (j) thì có 2 trường hợp:
    + TH1: người cuối cùng không có phần thưởng, tức là chỉ chia i phần thưởng cho j-1 người, trường hợp này số cách chia là C[ i ][ j-1 ].
    + TH2: 
    người cuối cùng chắc chắn có phần thưởng, khi đó ta sẽ lấy j phần thưởng chia cho j người, mỗi người sẽ có được 1 phần thưởng trước, lúc này còn lại i-j phần thưởng, tiếp tục lấy số còn lại này chia cho j người, trường hợp này số cách chia là C[i-j][j].
    Như vậy với mọi i>=j, C[ i ] [ j ] = C[ i ][ j-1 ] + C[ i-j ][ j ].
Cài đặt bằng ngôn ngữ Pascal:
PROGRAM chia_phan_thuong;
VAR C:ARRAY[0..70,0..70] OF LONGINT;
    m,n,i,j:INTEGER;
BEGIN
    write('So phan thuong: ')readln(m);
    write('So hoc sinh: ')readln(n);
    FOR i:=TO m DO C[i,0]:=0;
    FOR j:=TO n DO C[0,j]:=1;
    FOR i:=TO m DO
        FOR j:=TO n DO
            IF i<j THEN
                C[i,j]:=C[i,i]
            ELSE
                C[i,j]:=C[i,j-1] + C[i-j,j];
     writeln('So cach chia: ',C[m,n]);
     readln
END.
Cài đặt bằng ngôn ngữ C++
#include <iostream>
using namespace std;
int m,n;
int C[71][71];

int main()
{
    cin>>m>>n;
    int i,j;
    for (i=1; i<=m; i++) C[i][0]=0;
    for (j=1; j<=n; j++) C[0][j]=1;
    for (i=1; i<=m; i++)
        for (j=1; j<=n; j++)
            if (i<j)
                C[i][j] = C[i][i];
            else
                C[i][j] = C[i][j-1] + C[i-j][j];
    cout<<C[m][n]<<endl;
    return 0;
}
2. Phương pháp vét cạn:
Cài đặt bằng ngôn ngữ Pascal:
PROGRAM chia_phan_thuong;
VAR m,n,r:LONGINT;
    P:ARRAY[0..70] OF LONGINT;

PROCEDURE Chia(i,j:LONGINT){Chia i phan thuong cho nhung nguoi tu vi tri thu j}
VAR k:INTEGER;
BEGIN
    IF (j>n) THEN   {Da xet xong n nguoi}
    BEGIN
        IF i=THEN {Chia het toan bo phan thuong}
            BEGIN
                inc(r);{Tang so cach chia}
                FOR k:=TO n DO write(P[k],' ');{Xuat ra mot cach chia}
                writeln;
            END;
    END
    ELSE
        FOR k:=P[j-1] DOWNTO 0 DO {So phan thuong cua nguoi sau phai nho hon hoac bang cua nguoi truoc}
        IF i-k>=THEN {So phan thuong con lai phai khong am}
            BEGIN
                P[j]:=k;
                Chia(i-k,j+1){Chia so phan thuong con lai cho nhung nguoi sau.}
            END;
END;

BEGIN
    readln(m,n);
    r:=0;
    P[0]:=m;
    Chia(m,1);
    writeln('Co ',r,' cach chia!');
    readln;
END.
Cài đặt bằng ngôn ngữ C++
#include <iostream>
using namespace std;
int m,n,r;
int P[71];

void Chia(int m, int n)
{
    if (n>::n)
    {
        if (m==0)
        {
            r++;
            for (int i=1; i<=::n; i++) cout<<P[i]<<" ";
            cout<<endl;
        }
    }
    else
        for (int i=P[n-1]; i>=0; i--)
            if (m-i>=0)
            {
                P[n]=i;
                Chia(m-i,n+1);
            }
}

int main()
{
    cin>>m>>n;
    r=0;
    P[0]=m;
    Chia(m,1);
    cout<<"Co "<<r<<" cach chia!"<<endl;
    return 0;
}

nguồn: kithuatlaptrinh.tk
Share this post
  • Share to Facebook
  • Share to Twitter
  • Share to Google+
  • Share to Stumble Upon
  • Share to Evernote
  • Share to Blogger
  • Share to Email
  • Share to Yahoo Messenger
  • More...

0 nhận xét

:) :-) :)) =)) :( :-( :(( :d :-d @-) :p :o :>) (o) [-( :-? (p) :-s (m) 8-) :-t :-b b-( :-# =p~ :-$ (b) (f) x-) (k) (h) (c) cheer

 
© Download do an khoa luan tai lieu
Designed by BlogThietKe Cooperated with Duy Pham
Released under Creative Commons 3.0 CC BY-NC 3.0
Posts RSSComments RSS
Back to top