Hiển thị các bài đăng có nhãn Tham Lam. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Tham Lam. Hiển thị tất cả bài đăng
PTIT121G - Quan hệ

PTIT121G - Quan hệ

Link Sub: http://www.spoj.com/PTIT/problems/PTIT121G/
Người Gửi: Dương Lee

  • Problem:

Có N người mang tên tương ứng là 1, 2, ..., N và tình trạng quen biết của N người này được cho bởi mảng đối xứng A[1..N][1..N] trong đó A[i][j] = A[j][i] = 1 nếu i quen j và bằng 0 nếu i không quen j (quy ước A[i,i]=0). Hãy xét xem liệu có thể chia N người đó thành 2 nhóm mà trong mỗi nhóm hai người bất kì đều không quen nhau?
Input
Gồm nhiều bộ test, mỗi bộ test có dạng như sau:  
- Dòng thứ nhất: Ghi số nguyên dương 1<=N <= 100  
- N dòng tiếp theo, dòng thứ i ghi N số A[i][1], ..., A[i][N].
Bộ test kết thúc bởi dòng chứa số N=0.
Output
Với mỗi bộ test, in ra trên một dòng:  
- ‘YES’ nếu có thể chia.  
- ‘NO’ nếu không thể chia.
Example:
Input
11
0 1 0 0 1 1 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 1 0 0
1 0 0 1 0 0 0 0 0 0 0
1 0 0 1 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 1 0
0 0 0 0 0 0 0 0 1 1 0
0 0 0 1 0 0 0 1 0 0 0
0 0 0 0 0 0 1 1 0 0 1
0 0 0 0 0 0 0 0 0 1 0
0
Output:
YES

  • Solution:

- Với bài này chỉ có 2 nhóm và N nhỏ nên ta có thể giải quyết như sau:
Với mỗi một người ta kiểm tra xem có quen biết với bất kì người nào nào trong 2 nhóm N1 và N2 không?
+ Nếu có quen biết người trong N1 và không quen người nào trong N2 ta cho người đó vào N2;
Nếu có quen biết người trong N2 và không quen người nào trong N1 ta cho người đó vào N1;
Nếu có quen biết người trong N1 và có quen biết người trong N2 ta không thể làm thỏa mãn yêu cầu.
+ Nếu có không quen người nào trong N1 và không quen người nào trong N2 ta cho người đó vào N1.
Lưu Ý: N==1 vẫn thỏa mãn YES @@

  • Code:

C++:

https://ideone.com/O7gxFy
#include <iostream>
#include <vector>
using namespace std;
 
int N;
int A[102][102];
int read ()
{
    cin>>N;
    if (N==0) return 0;
    for (int i=1; i<=N; i++)
    {
        for (int j=1; j<=N; j++)
        {
            cin>>A[i][j];
        }
    }
    return 1;
}
 
int phanNhom()
{
    vector <int> N1;
    vector <int> N2;
    for (int i=1; i<=N; i++)
    {
        int kt1=0;
        for (int j=0; j<N1.size(); j++)
        {
            if (A[i][N1[j]]==1)
            {
                kt1 = 1;
                break;
            }
        }
        int kt2=0;
        for (int j=0; j<N2.size(); j++)
        {
            if (A[i][N2[j]]==1)
            {
                kt2 = 1;
                break;
            }
        }
        if (kt1==1 && kt2==0)
            N2.push_back(i);
        else if (kt1==0 && kt2==1)
            N1.push_back(i);
        else if (kt1==1 && kt2==1)
            return 0;
        else
            N1.push_back(i);
    }
    return 1;
}
 
int main ()
{
    while (read())
    {
        if (phanNhom()==1)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
} 

JAVA:

...

Python:

...
P171PROF - ROUND 1F - Học Bổng

P171PROF - ROUND 1F - Học Bổng

Link Sub: http://www.spoj.com/PTIT/problems/P171PROF/
Người Gửi: Dương Lee

  • Problem:

Sau một học kì học tập vất vả. Giờ Cường đang đi nhận học bổng, nhưng mà có rất nhiều người đang đợi như cường và họ phải xếp hàng. Cường muốn cải thiện thời gian chờ đợi để nhanh được ra tiệm net.  
Có n người đang đợi để nhận học bổng. với mọi người chúng ta đều biết trước thời gian mà người đó cần để hoàn thành thủ tục. Một người sẽ thất vọng khi thời gian người đó chờ đợi nhiều hơn thời gian mà họ làm thủ tục. Thời gian một người chờ đợi là tổng thời gian khi tất cả những người đứng trong hàng đợi trước mặt mình được làm thủ tục. Cường nghĩ rằng nếu trao đổi một số người thì có thể giảm số người thất vọng.  
Bạn hãy giúp cường tìm ra số lượng người tối đa không phải thất vọng khi đợi học bổng.


Input
Dòng đầu tiên chứa số nguyên n ( 1 ≤  n  ≤ 105 ).
Dòng tiếp theo chứa n số nguyên ti ( 1 ≤  ti  ≤ 109 ), cách nhau bằng dấu cách.
Output
In một số duy nhất - số lượng tối đa của mọi người không thất vọng trong hàng đợi.
Example:
Input
5
15 2 1 5 3
Output:
4

  • Solution:

- Tối ưu ban đầu: Sắp xếp cho dãy tăng dần code dưới đây dùng sort trong thư viện (heap sort).
- Sau khi đã có dãy tăng dần ta áp dụng phương án tối ưu sau: Tại mỗi phần tử (t[i]) ta tính tổng tất cả các số trước nó (S).
+ Nếu S<=t[i] thì người đó không bị thất vọng.
+ Nếu S>t[i] thì người đó sẽ thất vọng và ta sẽ gán t[i]=0. Vì sao lại = 0? Vì ta coi người đó bị thất vọng và coi như chuyển người đó về cuối dãy.
(Thực chất bài này là tìm dãy con có F[i]>=sum(F[i-j], j:=1->i) mà dài nhất. Nhưng vì n=10^5 nên ta có thể dùng tham lam giả QHĐ)

  • Code:

C++:

https://ideone.com/cT1DZ3
#include <iostream>
#include <algorithm>
using namespace std;

main ()
{
    long n;
    cin>>n;
    long long t[n];
    for (int i=0; i<n; i++)
    {
        cin>>t[i];
    }
    
    sort (t, t+n);
    
    long dem=1;
    for (int i=1; i<n; i++)
    {
        long long s=0;
        for (int j=0; j<i; j++)
        {
            s=s+t[j];
        }
        if (s<=t[i])
        {
            dem++;
        }
        else
        {
            t[i]=0;
        }
    }
    cout<<dem;
} 

JAVA:

...

Python:

...
PTIT122G - Số đối xứng 2

PTIT122G - Số đối xứng 2

Người Gửi: Sai

  • Problem:

Cho một số nguyên N (có thể chứa các số 0 ở đầu). Hỏi phải cộng thêm tối thiểu bao nhiêu để N trở thành số đối xứng (số cộng thêm là một số nguyên không âm - khi cộng tính cả các số 0 ở đầu nhé).
Input
Gồm nhiều bộ test, mỗi bộ test gồm một dòng chứa số nguyên N – có từ 2 đến 9 chữ số, không có dấu cách, có thể có các số 0 ở đầu.  
Dữ liệu vào kết thúc bởi dòng chứa số 0.
Output
Mỗi bộ test in trên một dòng chứa kết quả của bộ test.
Example:
Input
100000
100001
00456
000121
0
Output:
1
0
979
44

  • Solution:


- Phương án tốt nhất là:
 + Với mỗi cặp số tại i và n-1-i (n là length xâu) (VD: 12345 có các cặp số là 1-5, 2-4, 3-3)
 + Nếu mỗi cặp có [i] = [n-1-i] thì không cần xét đến vì nó đã đối xứng rồi. (VD: 1405231 thì cặp 1-1 không phải xét nữa).
 + Nếu cặp [i] > [n-1-i] thì chỉ cần chuyển [n-1-i]=[i] (VD: 1405231 -> 1415241 : cặp 4-3 -> 4-4)
+ Nếu cặp [i] < [n-1-i] thỉ chuyển [n-1-i]=[i] và tăng tiếp các số [n-1-i-j] thêm 1 nếu còn nhớ 1 (j:(1->i)) (VD: 1415241 -> 1416141 : cặp 1-2 -> 1-1 và 5 thêm 1->6)
  *Tại sao lại tăng thêm 1? Vì để chuyển 2->1 thì số phải chạy qua 10, có nghĩa là 2+9=11 ->lấy 11/10 -> 1 nên phải tăng thêm vào số kề trước nó để đúng quy tắc cộng số (vì đây là cộng số tạo đối xứng vậy nên nếu không tăng thêm theo quy tắc cộng số thì số tạo ra có thể < số ban đầu).
 *Tại sao lại tăng thêm 1 nếu còn nhớ 1? VD: 1992 -> 1991 (nhớ 1) -> 2001 -> 2002; => Nếu chỉ nhớ 1 lần thì chỉ tạo ra 1992 -> 1901. Vậy nên nếu cộng vào số tiếp theo mà vẫn còn tiếp tục nhớ 1 thì phải tiếp tục cộng thêm 1 cho số tiếp theo cho đến khi nhớ 0.
1410141 -> 1410141
Quá trình lặp lại cho đến khi tạo được số đối xứng. VD: 1409231 -> 1409241 1409241 -> 1409041 (nhớ 1) -> 1410041 1410041 -> 1410141
 

  • Code:

C++:



JAVA:


P144SUMI - ROUND 4I - Chia phần

Link Sub: http://www.spoj.com/PTIT/problems/P144SUMI/
Người Gửi: Dương Lee

  • Problem:

Sau giờ học, Tí cùng các bạn rủ nhau đi ăn xúc xích. Mọi người cùng nhau góp tiền. Có tất cả M người nhưng số tiền mà Tí cùng các bạn có chỉ mua được N cái xúc xích.  
Để cho công bằng thì Tí sẽ chia đều N chiếc xúc xích cho tất cả mọi người. Với một con dao trong tay, các bạn hãy giúp Tí tính xem Tí cần cắt ít nhất bao nhiêu phát?

Input
Gồm 2 số nguyên n và m (n, m <= 100).
Output
In ra một số nguyên duy nhất là đáp án của bài toán.
Example:
Input
2 6
Output:
4

Input
3 4
Output:
3
Input
6 2
Output:
0
  • Solution:

Giải thích test 1:  Có 2 cái xúc xích và cần chia ra thành 6 phần, Tí sẽ cắt mỗi chiếc xúc xích ra thành 3 phần đều nhau, như vậy cần tổng cộng 4 lát cắt.
Cách làm:
- Áp dụng tham lam như hình vẽ:
Trên hình là cách chia 3 xúc xích cho 4 người (Vạch đỏ là nơi cắt xúc xích) - Như vậy: + Lấy bội chung của số xúc xích và số người ta sẽ xác định được mỗi người sẽ cần tương ứng với bao nhiêu phần xúc xích. (Lấy bội chung thì lúc chia phần sẽ luôn nguyên). VD: 3 4 -> BC=12; -> một người cần 3 phần xúc xích. + Tham lam: Mỗi người ta sẽ lấy đủ phần xúc xích (thiếu thì lấy thêm không may lấy thừa thì sẽ cắt bớt). VD: người 1 cần 3 phần: + Lấy xúc xích 1: được 4 phần; (4 > 3: cắt bớt: cắt++; dư: 1 phần) -> người 1: đủ. + Lấy xúc xích 2: được 4 + 1 phần; (5 > 3: cắt bớt; cắt++; dư 2 phần) -> người 2: đủ. + lấy xúc xích 3: được 4 + 2 phần; (6 > 3: cắt bớt; cắt++; dư 3 phần) -> người 3: đủ. + Còn lại 3 phần cho người thứ 4;

  • Code:

C++:



JAVA:


PTIT125B - Mua quà

PTIT125B - Mua quà

Link Sub: http://www.spoj.com/PTIT/problems/PTIT125B/
Người Gửi: Funny

  • Problem:

FJ muốn mua quà cho N (1<=N<=1000) con bò của mình bằng cách sử dụng tổng số tiền là B (1<=B<=1,000,000,000).  
Bò i yêu cầu món quà có giá trị P(i) và có phí vận chuyển S(i) (nên tổng số tiền phải trả là P(i)+S(i) nếu FJ mua món quà đó). FJ có 1 phiếu giảm giá đặc biệt giúp anh có thể mua một món quà với giá bằng một nửa giá trị của món quà đó. Nếu FJ sử dụng phiếu giảm giá cho bò i, anh ấy cần phải thanh toán tổng số tiền là P(i)/2+S(i). 
Để cho dễ dàng, tất cả các P(i) đều là số chẵn.  Bạn hãy giúp FJ xác định xem ông có thể mua quà cho tối đa là bao nhiêu con bò.
Input
- Dòng 1: 2 số nguyên N và B  
- Dòng 2..1+N: Dòng i+1 chứa 2 số nguyên P(i) và S(i) (0<=P(i),S(i)<=1,000,000,000)
Output
Một số nguyên duy nhất là số bò tối đa mà FJ có thể mua quà
Example:
Input
5 24
4 2
2 0
8 1
6 3
12 5
Output:
4

  • Solution:

Giải thích: FJ có thể mua quà cho các con bò từ 1 đến 4, bằng cách sử dụng phiếu giảm giá cho bò 3. Tổng số tiền thanh toán là (4+2)+(2+0)+(4+1)+(6+3) = 22
- Ghi dữ liệu và đồng thời tính luôn độ giảm giá nếu áp dụng phiếu giảm. 
- Sắp xếp tăng dần giá các món hàng. 
- Mua lần lượt từ bé đến lớn, nếu còn mua được món hàng nào thì mua món hàng đó và cập nhật lại tiền. 
- Nếu đạt ngưỡng không mua tiếp được thì tìm con có độ giảm giá lớn nhất (trả lại hàng và lấy thêm tiền :v). Dùng tiền đã tăng thêm lại tiếp tục mua cho đến khi đạt ngưỡng không mua được. =))

  • Code:

C++:



JAVA:


PTIT013D - BÀI D - BÀN CỜ

PTIT013D - BÀI D - BÀN CỜ

Link Sub: http://www.spoj.com/PTIT/problems/PTIT013D/
Người Gửi: Dương Lee

  • Problem:

Cho bàn cờ kích thước n x n, gồm hàng ngang được đánh số từ 1 đến từ dưới lên trên và cột dọc được đánh số từ 1 đến n từ trái qua phải. Ô nằm trên giao của hàng i và cột j của bàn cờ ký hiệu là ô (i, j). Khi đặt con mã  lên bàn cờ, nó sẽ khống chế được tất cả các ô ở đỉnh đối diện trên đường chéo của hình chữ nhật kích thước 2×3.  Nhiệm vụ của bạn là viết một chương trình tính số quân mã tối đa đặt được lên bàn cờ mà không có hai quân mã nào khống chế nhau.
Input
Dữ liệu vào gồm nhiều bộ dữ liệu tương ứng với nhiều test. Dòng đầu tiên chứa một số nguyên dương không lớn hơn 20 là số lượng các bộ dữ liệu. Các dòng tiếp theo chứa các bộ dữ liệu.  
Mỗi bộ dữ liệu gồm một số nguyên n duy nhất (0 <= n <= 30).
Output
Với mỗi bộ dữ liệu, hay in ra đáp số của bài toán.
Example:
Input
2
4
8
Output:
8
32

  • Solution:

Cách đặt tối ưu nhất cho bài này là các bạn đặt so le: VD: 4 -> x.x. .x.x x.x. .x.x Sẽ có được số mã tối đa nhất có thể, Vậy chỉ cần biết được có bao nhiêu hàng là biết được bao nhiêu quân mã tối đa rồi. :D

  • Code:

C++:



JAVA:


P162PROG - ROUND 2G - Vi khuẩn

P162PROG - ROUND 2G - Vi khuẩn

Link Sub: http://www.spoj.com/PTIT/problems/P162PROG/
Người Gửi: dfg

  • Problem:

Tyrion nuôi cấy vi khuẩn trong 1 ống nghiệm. Ban đầu ống nghiệm rỗng. Mỗi sáng Tyrion có thể một lượng bất kỳ (có thể bằng 0) vi khuẩn vào ống nghiệm. Mỗi đêm, mỗi vi khuẩn trong ống sẽ tăng lên gấp đôi. Một ngày, Tyrion mong muốn nhìn thấy chính xác x vi khuẩn.
Hãy tính xem số lượng vi khuẩn tối thiểu Tyrion cần phải bỏ vào.
Input
Số nguyên x ( 1 <= x <= 1 000 000 000).
Output
In ra duy nhất 1 số là đáp án của bài toán.
Example:
Input
5
Output:
2

  • Solution:

Giải thích: Ngày thứ nhất Tyrion bỏ 1 vi khuẩn. Đến buổi sáng thứ 3, ông ta có 4 con vi khuẩn trong ống nghiệm. Ông ta bỏ thêm 1 con nữa là sẽ có 5.
Cách làm: Cho một con và để cho nó phát triển max (lớn nhất mà <= X). Nếu chưa đủ thì cho tiếp thêm 1 con nữa vào để phát triển lại với X đã được cập nhật trước đó.

  • Code:

C++:



JAVA:


PTIT127C - Bố trí phòng họp

Link Sub: http://www.spoj.com/PTIT/problems/PTIT127C/
Người Gửi: Default

  • Problem:

Có n cuộc họp đánh số từ 1 đến n đăng ký làm việc tại một phòng hội thảo. Cuộc họp i cần được bắt đầu ngay sau thời điểm si và kết thúc tại thời điểm f­i. Hỏi có thể bố trí phòng hội thảo phục vụ được nhiều nhất bao nhiêu cuộc họp, sao cho khoảng thời gian làm việc của hai cuộc họp bất kỳ là không giao nhau.
Input
Dòng đầu tiên chứa số nguyên dương n ( n <= 10000) 
Dòng thứ i trong số n dòng tiếp theo chứa hai số nguyên dương si, fi (si < fi <= 32000) ( 1 <= i <= n).
Output
Dòng đầu tiên ghi số K là số các cuộc họp được chấp nhận phục vụ

Example:
Input
5
7 9
2 4
1 3
1 6
3 7
Output:
3

  • Solution:

Bài này tham lam đúng là: 
- Sắp xếp tăng dần các giờ f 
- Chạy từng khung giờ sao cho giờ tiếp theo phải >= giờ f.

  • Code:

C++:



JAVA: