Hiển thị các bài đăng có nhãn Đồ Thị. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Đồ Thị. Hiển thị tất cả bài đăng
PTIT121K - Đường đi lớn nhất

PTIT121K - Đường đi lớn nhất

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

  • Problem:

Sau những tiết học ban đầu hứng thú với môn Điện tử số về hệ cơ số, MĐ dần thấy nản khi phải đối mặt với các loại mạch và cổng @@. Đầu óc cứ nghĩ đến mấy cái hệ cơ số, MĐ lại nghĩ ra một bài toán khác để thử tài các bạn SV PTIT :D. Bài toán như sau:  
Cho một bảng vuông (n x n) ô (2<=n<=100) các ô ghi các số là 0 hoặc 1. Bạn hãy tìm đường đi từ góc trái trên xuống góc phải dưới theo nguyên tắc chỉ được dịch chuyển sang phải và xuống dưới sao cho các số trên đường đi tạo thành một số nhị phân có giá trị lớn nhất.
Input
-  Dòng đầu tiên ghi giá trị n  
-  n dòng tiếp theo, trên mỗi dòng ghi n số 0 hoặc 1 các số này cách nhau ít nhất một khoảng trắng.
Output
-  Một số duy nhất là giá trị trong hệ cơ số 16 của số nhị phân được tạo thành ở trên.
Example:
Input
5
1 0 1 1 0
0 0 1 0 1
0 0 1 0 1
1 0 0 1 1
1 1 0 1 0
Output:
176

  • Solution:

- Đối với những bài dạng di chuyển chỉ phải - xuống, lên - trái ta có thể dùng quy hoạch động đơn giản để xét các trạng thái của nó tại mỗi vị trí.
- Ta có dãy các nhị phân: F[][] là mảng max dãy nhị phân. F[i][j] = max(F[i-1][j], F[i][j-1])+(char)(arr[i][j]);
- Sau đó là chuyển dãy nhị phân trên thành dãy các mã hệ 16 (Hex). Code dưới đây chuyển xâu bit thành xâu bit có độ dài chia hết cho 4 và xét 4 bít một để chuyển về Hex (Không thừa số 0 ở đầu).

  • Code:

C++:

https://ideone.com/OMPxBJ
#include <iostream>
#include <math.h>
using namespace std;

int n;
int arr[102][102];
void read ()
{
    cin>>n;
    for (int i=1; i<=n; i++)
        for (int j=1; j<=n; j++)
            cin>>arr[i][j];
}

string F[102][102];
string He2 ()
{
    for (int i=1; i<=n; i++)
    {
        F[0][i]="";
        F[i][0]="";
    }
    
    for (int i=1; i<=n; i++)
    {
        for (int j=1; j<=n; j++)
        {
            char tmp = (arr[i][j]+'0');
            F[i][j] = max(F[i-1][j], F[i][j-1])+tmp;
        }
    }
    return F[n][n];
}

string BinToHex (string x)
{
    string rs = "";
    while (x.size()%4!=0)
        x="0"+x;
    
    for (int i=0; i<x.size(); i=i+4)
    {
        string tmp = x.substr(i, 4);
        int d = 0;
        for (int j=0; j<4; j++)
        {
            d+=((tmp[j]-'0')*pow(2,(3-j)));
        }
        char c;
        if (d>=0 && d<=9)
            c = d+'0';
        else
            c = d-10+'A';
        rs = rs+c;
    }
    if (rs=="") return "0";
    else
    {
        while (1)
        {
            if (rs.size()-1==0 || rs[0]!='0') break;
            rs.erase(rs.begin(), rs.begin()+1);
        }
    }
    return rs;
}

int main ()
{
    read ();
    string He2Max = He2();
//    cout<<He2Max<<endl;
    cout<<BinToHex(He2Max);
    return 0;
}

JAVA:

...

Python:

...
PTIT124E - Họp mặt

PTIT124E - Họp mặt

Người Gửi: Sai

  • Problem:

Có K người (1 ≤ K ≤ 100) đứng tại vị trí nào đó trong N địa điểm cho trước (1 ≤ N ≤ 1,000) được đánh số từ 1..N. Các điểm được nối với nhau bởi M đoạn đường một chiều (1 ≤ M ≤ 10,000) (không có đoạn đường nào nối một điểm với chính nó).  
Mọi người muốn cùng tụ họp tại một địa điểm nào đó. Tuy nhiên, với các đường đi cho trước, chỉ có một số địa điểm nào đó có thể được chọn là điểm họp mặt. Cho trước K, N, M và vị trí ban đầu của K người cùng với M đường đi một chiều, hãy xác định xem có bao nhiêu điểm có thể được chọn làm điểm họp mặt.
Input
Dòng 1: Ghi 3 số: K, N, và M  Dòng 2 đến K+1: dòng i+1 chứa một số nguyên trong khoảng (1..N) cho biết địa điểm mà người thứ i đang đứng.  
Dòng K+2 đến M+K+1: Mỗi dòng ghi một cặp số A và B mô tả một đoạn đường đi một chiều từ A đến B (cả hai trong khoảng 1..N và A != B).
Output
Số địa điểm có thể được chọn là điểm họp mặt.
Example:
Input
2 4 4
2
3
1 2
1 4
2 3
3 4
Output:
2

  • Solution:

Giải thích test ví dụ: có thể họp mặt tại điểm 3 và điểm 4.
Cách làm chính: "loang". - Với mỗi người sẽ loang toàn bộ các điểm mà nó có thể đến được (tư tưởng theo DFS) bằng đệ quy - Đồng thời với mỗi điểm sẽ đếm xem có bao nhiêu người duyệt qua nó. - Kiểm tra lại các điểm: Với mỗi điểm nếu đếm = K lần duyệt thì đỉnh đó có thể họp mặt đủ K người. (*Chú ý: Sử dụng danh sách kề để giảm độ phức tạp xuống còn O(max(N,M)));

  • Code:

C++:



JAVA:


BCISLAND - Nước biển

BCISLAND - Nước biển

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

  • Problem:

Trái đất nóng lên kéo theo mực nước biển dâng. Hòn đảo nhỏ Gonnasinka thuê bạn để dự báo trước hiểm họa này. Cho trước 1 lưới tọa độ thể hiện cao độ của đảo, hãy giúp họ tính toán xem nước biển dâng cao bao nhiêu thì hòn đảo sẽ bị chia cắt.
Input
Input gồm nhiều bộ test, mỗi bộ test bao gồm:  
Dòng đầu ghi 2 số n, m là chiều dài và chiều rộng. 
Sau đó là n dòng, mỗi dòng gồm m số, mỗi số cho biết độ cao của ô đó, giá trị 0 chỉ mực nước biển. Những ô giá trị 0 dọc theo đường viền và những ô số 0 liền kề những ô này chỉ mặt biển. Những ô có giá trị 0 còn lại (được bao bọc bởi các số > 0) là đất liền bên trong đảo nhưng có độ cao ngang mặt nước biển. Hòn đảo lúc đầu chưa bị chia cắt. Số n và m không lớn hơn 100 và độ cao không lớn hơn 1000. 
Dòng cuối cùng của input chứa 2 số 0
Output
Với mỗi bộ test, in ra:  
Case n: Island splits when ocean raises f feet. (Đảo bị chia khi nước biển dâng cao f feet)  
Hoặc  
Case n: Island never splits. (Đảo không bao giờ bị chia cắt)
Example:
Input
5 5
3 4 3 0 0
3 5 5 4 3
2 5 4 4 3
1 3 0 0 0
1 2 1 0 0
5 5
5 5 5 5 7
4 1 1 1 4
4 1 2 1 3
7 1 0 0 4
7 3 4 4 4
0 0
Output:
Case 1: Island never splits.
Case 2: Island splits when ocean rises 3 feet.

  • Solution:

- Bài này chia ra làm các bước như sau: + B1: Tìm độ cao lớn nhất so với mặt nước biển. (Hmax) + B2: Với độ cao tăng thêm: extra = 1->Hmax ta sẽ loang bắt đầu từ các cạnh là biển loang vào những nới có độ (độ cao <= extra). VD: có bản đồ: 5 5 5 5 7 4 1 1 1 4 4 1 2 1 3 7 1 0 0 4 7 3 4 4 4 với extra=1 ta thu được check[][]: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +B3: Đếm số thành phần liên thông tại check[][] với các check[][]==0 bằng DFS; Số thành phần liên thông > 1 thì tại độ cao extra đó đảo bị chia cắt; VD: ở bản đồ trên tại extra = 3 ta có check[][]: 0 0 0 0 0 0 1 1 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 0 0

  • Code:

C++:



JAVA:


PTIT126H - Đọng nước

PTIT126H - Đọng nước

Người Gửi: Dương Lee

  • Problem:


Nền phẳng của một công trường xây dựng đã được chia thành lưới ô vuông đơn vị kích thước mxn ô. Trên mỗi ô (i, j) của lưới, người ta dựng một cột bê tông hình hộp có đáy là ô (i, j) và chiều cao là Hij đơn vị. Sau khi dựng xong, thì trời đổ mưa to và đủ lâu. Giả thiết rằng nước không thẩm thấu qua các cột bê tông cũng như không rò rỉ qua các đường ghép giữa chúng.
Yêu cầu: Xác định lượng nước đọng giữa các cột
Chú ý: m, n, H­ij là các số nguyên dương. 1 <= m, n <= 100. 1 <= Hij­ <= 1000
Input

Dòng 1:
m n
Dòng 2:
H11 H12 ... H1n
Dòng 3:
H21 H22 ... H2n
...
...
Dòng m + 1:
Hm1 Hm2 ... Hmn
Các số trên 1 dòng các nhau ít nhất 1 dấu cách
Output
Số đơn vị khối nước đọng
Example:
Input
5 5
9 9 9 9 9
9 2 2 2 9
9 2 1 2 9
9 2 2 2 9
9 9 9 9 9
Output:
64

  • Solution:

*Ý tưởng: - Ta xét từng phân khúc từ dưới lên (giống chặt cây thành từng đoạn có độ cao là 1); - Xét đường biên nếu biên thấp hơn bên trong thì đánh dấu bên trong không có nước đọng. - Duyệt lại và đếm xem có bao nhiêu ô có nước đọng. *Thực hiện: - Tạo mảng riêng H_Sp với các chỉ số 0 và 1; - Mảng riêng có đặc điểm: + Tại hàng i, cột j: H[i][j]<1?H_Sp[i][j]=0:H_Sp[i][j]=1; và H[i][j]--; VD: 1 1 0 3 0 2 1 1 1 -> Chặt lần 1 sẽ thu được: H_Sp: 1 1 0 1 0 1 1 1 1 H: 0 0 0 2 0 1 0 0 0 + Sẽ chặt cho đến khi Hmax =0; + Với mỗi H_Sp thu được sẽ duyệt đường biên nếu biên H_Sp[i][j]==0? thì có nghĩa là đường biên này đang thấp hơn các cột khác. -> Ta sẽ loang từ biên loang vào 4 phía, đánh dấu các ô ==0 -> 1 (Bước này dùng để xác định tại các ô đó sẽ không có nước đọng) VD: với H_Sp trên khi loang vào sẽ được: 1 1 1 1 0 1 1 1 1 + Cuối cùng thì chỉ cần duyệt lại mảng H_Sp để đếm các ô ==0 (nước đọng) và lặp lại quá trình cho đến Hmax=0;

  • Code:

C++:



JAVA:


PBCWATER - Tính toán lượng nước

PBCWATER - Tính toán lượng nước

Người Gửi: Dương Lee

  • Problem:


Nền phẳng của 1 công trình xây dựng được chia thành lưới ô vuông đơn vị kích thước  MxN ô. Trên mỗi ô (i,j) của lưới, người ta dựng 1 cột bê tông hình hộp có đáy là ô (i,j) và chiều cao là h[i,j] đơn vị. Sau khi dựng xong thì trời đổ mưa to và đủ lâu. Nhà thầu xây dựng muốn tính lượng nước đọng lại giữa các cột để có kế hoạch thi công tiếp theo. Giả thiết, nước ko thẩm thấu qua các cột bê tông cũng như ko rò rỉ qua các đường ghép giữa chúng.
Nhiệm vụ của bạn là giúp nhà thầu tính toán lượng nước đọng lại giữa các cột.


Input

Dòng đầu tiên ghi 2 số nguyên dương M và N  
Dòng thứ i trong M dòng tiếp theo, ghi N số nguyên dương h[i,1],h[i,2]...h[i,N].
Giới hạn:     1<=M,N<=100,1<=H[i,j]<=1000
Output
1 dòng duy nhất chứa số đơn vị khối nước đọng lại.
Example:
Input
5 5
9 9 9 9 9
9 2 2 2 9
9 2 5 2 9
9 2 2 2 9
9 9 9 9 9
Output:
60

  • Solution:

*Ý tưởng: - Ta xét từng phân khúc từ dưới lên (giống chặt cây thành từng đoạn có độ cao là 1); - Xét đường biên nếu biên thấp hơn bên trong thì đánh dấu bên trong không có nước đọng. - Duyệt lại và đếm xem có bao nhiêu ô có nước đọng. *Thực hiện: - Tạo mảng riêng H_Sp với các chỉ số 0 và 1; - Mảng riêng có đặc điểm: + Tại hàng i, cột j: H[i][j]<1?H_Sp[i][j]=0:H_Sp[i][j]=1; và H[i][j]--; VD: 1 1 0 3 0 2 1 1 1 -> Chặt lần 1 sẽ thu được: H_Sp: 1 1 0 1 0 1 1 1 1 H: 0 0 0 2 0 1 0 0 0 + Sẽ chặt cho đến khi Hmax =0; + Với mỗi H_Sp thu được sẽ duyệt đường biên nếu biên H_Sp[i][j]==0? thì có nghĩa là đường biên này đang thấp hơn các cột khác. -> Ta sẽ loang từ biên loang vào 4 phía, đánh dấu các ô ==0 -> 1 (Bước này dùng để xác định tại các ô đó sẽ không có nước đọng) VD: với H_Sp trên khi loang vào sẽ được: 1 1 1 1 0 1 1 1 1 + Cuối cùng thì chỉ cần duyệt lại mảng H_Sp để đếm các ô ==0 (nước đọng) và lặp lại quá trình cho đến Hmax=0;

  • Code:

C++:



JAVA:


BCLKCOUN - Đếm số ao

BCLKCOUN - Đếm số ao

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

  • Problem:

Sau khi kết thúc OLP Tin Học SV, một số OLP-er quyết định đầu tư thuê đất để trồng rau.
Mảnh đất thuê là một hình chữ nhật N x M (1<=N<=100; 1<=M<=100) ô đất hình vuông.
Nhưng chỉ sau đó vài ngày, trận lụt khủng khiếp đã diễn ra làm một số ô đất bị ngập :((
Due to recent rains, water has pooled in various places in Farmer
John's field, which is represented by a rectangle of N x M (1 <= N
<= 100; 1 <= M <= 100) squares. Each square contains either water
('W') or dry land ('.'). Farmer John would like to figure out how
many ponds have formed in his field.  A pond is a connected set of
squares with water in them, where a square is considered adjacent
to all eight of its neighbors.
Given a diagram of Farmer John's field, determine how many ponds he has.
PROBLEM NAME: lkcount
INPUT FORMAT:
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: M characters per line representing one row of Farmer
        John's field.  Each character is either 'W' or '.'.  The
        characters do not have spaces between them.
SAMPLE INPUT (file lkcount.in):
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
OUTPUT FORMAT:
* Line 1: The number of ponds in Farmer John's field.
SAMPLE OUTPUT (file lkcount.out):
3
OUTPUT DETAILS:
There are three ponds: one in the upper left, one in the lower left,
and one along the right side.
Mảnh đất biến thành một số các ao. Các OLP-er quyết định chuyển sang nuôi cá :D Vấn đề lại
nảy sinh, các OLP-er muốn biết mảnh đất chia thành bao nhiêu cái ao để có thể tính toán
nuôi trồng hợp lý. Bạn hãy giúp các bạn ý nhé.
Chú ý: Ao là gồm một số ô đất bị ngập có chung đỉnh. Dễ nhận thấy là một ô đất có thể có tối đa 8 ô chung đỉnh.

Input
* Dòng1: 2 số nguyên cách nhau bởi dấu cách: N và M      
* Dòng 2..N+1: M kí tự liên tiếp nhau mỗi dòng đại diện cho 1 hàng các ô đất.  
Mỗi kí tự là 'W' hoặc '.' tương ứng với ô đất đã bị ngập và ô đất vẫn còn nguyên.
Output
* Dòng 1: 1 dòng chứa 1 số nguyên duy nhất là số ao tạo thành.
Example:
Input
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
Output:
3

  • Solution:

Bài này mình sử dụng phương pháp DFS đệ quy tìm số thành phần liên thông. 
Sơ lược qua về khởi tạo ban đầu: 
- Tạo dinh[R][C]: với lần lượt các đỉnh từ 1->R*C; 
- Duyệt theo 8 hướng (lên, lên trái, trái, xuống trái, xuống, xuống phải, phải, lên phải) và đánh dấu; 
Các bạn cũng có thể sử dụng BFS.

  • Code:

C++:



JAVA: