P145SUMH - ROUND 5H - Hệ thống điện

P145SUMH - ROUND 5H - Hệ thống điện

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

  • Problem:

Khu vực nhà Tí bị mất điện dài ngày để khắc phục sự cố đường dây 500 kV. Các kỹ sư bảo rằng khu vực này có khi mất điện đến cả tháng trời. Vì vậy, các hộ dân ở đây đã sử dụng máy phát điện. Không phải hộ gia đình nào cũng có, vì vậy, họ đã kết nối với nhau để tạo thành hệ thống lưới điện riêng. Rõ ràng những gia đình nào ở càng xa nguồn phát thì điện sẽ càng yếu.  
Tí muốn biết xem trong khu vực của mình, gia đình nào điện sẽ yếu nhất?  
Độ yếu của điện tại hộ gia đình X được tính bằng 0 nếu hộ đó là hộ phát điện, nếu hộ X có kết nối điện với hộ Y mà hộ Y ở gần máy phát hơn, độ yếu tại hộ X = độ yếu tại hộ Y + 1. Nếu hộ X không có điện thì có độ yếu bằng vô cùng (infinity).
Input
Dòng đầu tiên gồm 3 số nguyên N, M, H lần lượt là số hộ gia đình, M là số hộ gia đình có máy phát điện, H là số kết nối 2 chiều. (N, M <= 1 000, H <= 10 000).  
Dòng tiếp theo gồm M số là ID các hộ gia đình có máy phát điện (ID đánh số từ 0 tới N-1).  
H dòng tiếp theo, mỗi dòng gồm 2 số u, v, cho biết hộ gia đình u có kết nối với hộ gia đình.
Output
In ra hộ gia đình có độ yếu của điện là cao nhất. Nếu có nhiều đáp án, in ra hộ có ID nhỏ nhất.
Example:
Input
6 3 5
0 5 2
0 1
1 2
4 5
3 5
0 2
Output:
1

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

Ban đầu coi tất cả các hộ gia đình có độ yếu của điện là: infinity (>1000 - vì chỉ có tối đa 1000 hộ)
Bài này sau khi setup hệ thống đường dây điện (chính là biểu diễn các hộ gia đình theo danh sách kề - biểu diễn đồ thị)
Chỉ cần BFS từ các điểm phát phát đếm bước đi ngắn nhất đến các căn hộ khác. Điện của max của mỗi hộ = min(tất cả trường hợp yếu điện từ nguồn phát đến hộ đó)
Cuối cùng độ yếu điện lớn nhất chính là max(điện tất cả các hộ).

  • Code:

C++:

https://ideone.com/C1yMXV
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int n, m, h;
vector< int > generator;
vector< int > line[1003];

void Read()
{
    cin>>n>>m>>h;
    for (int i=0; i<m; i++)
    {
        int tmp;
        cin>>tmp;
        generator.push_back(tmp);
    }
    for (int i=0; i<h; i++)
    {
        int a, b;
        cin>>a>>b;
        line[a].push_back(b);
        line[b].push_back(a);
    }
}

int weak[1003];

void Init()
{
    for (int i=0; i<n; i++)
    {
        weak[i] = 1003;
    }
}

int check[1003];
int trans[1003];
void Reset()
{
    for (int i=0; i<n; i++)
    {
        check[i] = 0;
        trans[i] = -1;
    }
}

void BFS(int u)
{
    check[u] = 1;
    queue<int> q;
    q.push(u);
    trans[u] = 0;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i=0; i<line[u].size(); i++)
        {
            int v = line[u][i];
            if (check[v] == 0)
            {
                q.push(v);
                check[v] = 1;
                trans[v] = trans[u] + 1;
            }
        }
    }
}

void CheckWeak()
{
    for (int i=0; i<n; i++)
    {
        if (trans[i]!=-1)
        {
            if (trans[i]<weak[i])
            {
                weak[i] = trans[i];
            }
        }
    }
}

void OUT()
{
    int p = 0;
    for (int i=1; i<n; i++)
    {
        if (weak[i] > weak[p])
        {
            p = i;
        }
    }
    cout<<p;
}

void Test()
{
    for (int i=0; i<n; i++)
    {
        cout<<check[i]<<" ";
    }
    cout<<endl;
    for (int i=0; i<n; i++)
    {
        cout<<trans[i]<<" ";
    }
    cout<<endl;
    for (int i=0; i<n; i++)
    {
        cout<<weak[i]<<" ";
    }
}



int main()
{
//    freopen("input.txt", "r", stdin);
    Read();
    Init();
    for (int i=0; i<m; i++)
    {
        Reset();
        BFS(generator[i]);
        CheckWeak();
    }
    OUT();
//    test();
    return 0;
}

JAVA:

...

Python:

...
P141SUMF - ROUND 1F - Ném đá

P141SUMF - ROUND 1F - Ném đá

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

  • Problem:

Trong khoảng 2 tuần, Zoro phải nằm trên giường vì bị bạn Nami vô tình ném 1 viên đá to vào chân trái. Vì Zoro đã hoàn thành hết nhiệm vụ nên anh ta phải tìm cách để giết thời gian.  
Trò chơi mới của Zoro được chơi trên 1 bảng kích thước R X C. Ban đầu, mỗi ô vuông được để trống hoặc bị chặn bởi 1 bức tường. Zoro ném 1 viên đá vào bảng bằng cách để nó vào hàng trên cùng của 1 cột và để trọng lực làm làm phần còn lại.  
Trọng lực hoạt động như sau: 
- Nếu ô vuông bên dưới viên đá là 1 bức tường chắn, hoặc nếu viên đá ở hàng cuối cùng của một cột thì nó ở yên chỗ đó.  
- Nếu ô vuông bên dưới viên đá để trống, nó sẽ di chuyển xuống ô đó.  
- Nếu ô vuông bên dưới viên đá, có 1 viên đá khác, viên đá có thể trượt sang 2 bên như sau:     
+ Nếu ô vuông bên trái, và ô dưới của ô bên trái trống, viên đá sẽ trượt sang ô bên trái.     
+ Nếu viên đá không trượt sang trái và ô vuông bên phải, ô dưới của ô bên phải trống, viên đá sẽ trượt sang phải.     
+ Còn lại, viên đá sẽ ở yên đó, và không di chuyển nữa.  
Zoro không bao giờ ném viên đá khác, khi viên đá trước chưa rơi cố định vào 1 ô nào đó.  
Viết 1 chương trình, vẽ cái bảng sau khi Zoro ném toàn bộ số viên đá của mình vào đó, giả sử chúng ta biết Zoro ném đá vào các cột, theo thứ tự.  
Chú ý : Zoro không bao giờ ném 1 viên đá vào 1 cột, nếu ô trên cùng của cột đó không trống.
Input
Dòng đầu tiên chứa số nguyên R và C, là kích thước của bảng (R, C <= 30).  
Mỗi dòng trong N dòng tiếp theo, chứa C kí tự, là sơ đồ ban đầu của bảng. Dấu '.' đại diện cho 1 ô trống, trong khi 'X' là 1 ô được chặn bởi tường.  
Dòng kế tiếp chứa số nguyên N, là số viên đá mà Zoro ném.  
Mỗi N dòng tiếp theo chứa 1 số nguyên giữa 1 và C, là cột mà Zoro ném viên đá vào (đánh số từ trái sang phải).
Output
In ra R dòng, mỗi dòng chứa C kí tự, là sơ đồ của bảng sau khi đã ném hết đá vào. Đá được kí hiệu bằng chữ cái “O”.
Example:
Input
5 4
....
....
X...
....
....
4
1
1
1
1
Output:
....
O...
X...
....
OOO.

Input
7 6
......
......
...XX.
......
......
.XX...
......
6
1
4
4
6
4
4
Output:
......
...O..
...XX.
......
.OO...
.XX...
O..O.O
  • Solution:

Bài này sử dụng đệ quy để tìm đường tiếp theo cho viên đá (Dựa vào dữ kiện của đề cung cấp là được).
Để tiện hơn thì mình tạo thêm một hàng rào 'X' bao xung quanh nữa để đỡ phải xét nhiều điều kiện. 
VD: 
Map:
...X.
.....
Thì giờ sẽ thành:
XXXXXXX
X...X.X
X.....X
XXXXXXX

  • Code:

C++:

https://ideone.com/SULbQ2
#include <iostream>
#include <vector>
using namespace std;

int r, c;
char m[35][35];
vector <int> v;

void read()
{
    cin>>r>>c;
    for (int i=0; i<=r+1; i++)
    {
        for (int j=0; j<=c+1; j++)
        {
            if (i==0 || i==r+1 || j==0 || j==c+1)
                m[i][j] = 'X';
            else
            {
                cin>>m[i][j];
            }
        }
    }

    int n;
    cin>>n;
    for (int i=0; i<n; i++)
    {
        int a;
        cin>>a;
        v.push_back(a);
    }
}

int findWay(int i, int j)
{
    if (m[i+1][j] == 'X')
    {
        m[i][j] = 'O';
        return 1;
    }
    else if (m[i+1][j] == '.')
    {
        findWay(i+1, j);
    }
    else if (m[i+1][j] == 'O')
    {
        if (m[i][j-1] == '.' && m[i+1][j-1] == '.')
        {
            findWay(i+1, j-1);
            return 1;
        }
        else if (m[i][j+1]=='.' && m[i+1][j+1] == '.')
        {
            findWay(i+1, j+1);
            return 1;
        }
        else
        {
            m[i][j] = 'O';
            return 1;
        }
    }
}

void out()
{
    for (int i=1; i<=r; i++)
    {
        for (int j=1; j<=c; j++)
        {
            cout<<m[i][j];
        }
        cout<<endl;
    }
}

void check()
{
    cout<<r<<" "<<c<<endl;
    for (int i=0; i<=r+1; i++)
    {
        for (int j=0; j<=c+1; j++)
        {
            cout<<m[i][j];
        }
        cout<<endl;
    }
    cout<<v.size()<<endl;
    for (int i=0; i<v.size(); i++)
        cout<<v[i]<<endl;
}

int main()
{
//    freopen("input.txt", "r", stdin);
    read();
    for (int i=0; i<v.size(); i++)
    {
        findWay(1, v[i]);
    }
    out();
//    check();
    return 0;
}

JAVA:

...

Python:

...