Announcement

Collapse
No announcement yet.

[Lập trình newbie] Mỗi ngày một bài toán (số 4)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • [Lập trình newbie] Mỗi ngày một bài toán (số 4)

    Hi all !, Trước tiên rất vui khi ba bạn Cao Văn Nhàn, quoctinvn , Lê Võ Thanh Hồng,......
    đã có những tranh luận sôi nổi giúp cho bài toán trở nên dễ hiểu hơn cho các bạn newbie khác. Hi vọng các bạn sẽ tiếp tục với bài toán khá dễ dưới đây
    :shy:.
    Bài toán: Hoán vị (QBHV)
    bài này nhằm cho các bạn nhớ lại những xử lý cơ bản về chuỗi là chính.

    Đề bài:
    Cho một xâu S chỉ gồm các chữ cái in hoa, 1 <= độ dài <= 9.


    Yêu cầu:
    1: Có bao nhiêu cách hoán vị các chữ cái của xâu S
    2: Liệt kê các hoán vị đó theo thứ tự từ điển


    Input

    Gồm 1 dòng duy nhất chứa xâu S


    Output

    Dòng 1: Ghi số lượng hoán vị tìm được (K)



    K dòng tiếp theo, mỗi dòng ghi một xâu hoán vị của xâu S theo đúng thứ tự từ điển

    Example
    Input:
    ABAB
    Output:
    6
    AABB
    ABAB
    ABBA
    BAAB
    BABA
    BBAA
    Từ từ đừng làm các em sợ nha hi :stick:
    Last edited by 09520281; 10-07-2012, 00:54.
    Facebook: Kiều Thắng
    Google Plus: Kiều Thắng
    Thông tin về du học các nước: Du học.


  • #2
    kinh thật.hic
    HEART TO HEART

    Comment


    • #3
      Bài này mình có 2 cách:
      1. Dùng đệ quy, sinh ra tất cả các hoán vị, lưu lại và đếm các hoán vị không trùng nhau. Vì n <= 9 nên có tối đa 9! = 362880 hoán vị. Để đếm các hoán vị không trùng nhau, nếu dùng tìm kiếm tuyến tính có thể sẽ bị quá thời gian (lỗi Time limit exceeded). Do đó, có thể sắp xếp lại rồi dùng tìm kiếm nhị phân (binary search).
      2. Trong thư viện algorithm (#include <algorithm> và using namespace std; ) có hàm next_permutation() tính ra hoán vị tiếp theo của 1 dãy cho trước. Mình dùng hàm này để tính và in ra các hoán vị. (Cách này ngắn gọn hơn cách trên)
      Last edited by 10520355; 10-07-2012, 11:50.
      University of Information Technology
      Cao Văn Nhàn _ CE10520355
      SĐT: 0188 403 4943

      Email: caovannhan2002@gmail.com

      Comment


      • #4
        Giới hạn bài này thì có thể dùng phương pháp duyệt, tuy nhiên không cần phải đệ quy sinh hoán vị rồi đếm các hoán vị không trùng nhau như anh Nhàn :haha: cách em làm :
        • Sort lại xâu ban đầu, gọi là xâu st
          Chừng nào xâu st chưa là xâu lớn nhất theo thứ tự từ điển
          Tìm từ cuối về đầu 2 vị trí i và j đầu tiên sao cho st[i] > st[j]; i>j.
          Swap st[i] và st[j]. Sort lại xâu con st từ vị trí j+1 đến cuối xâu.
          Cứ mỗi lần tìm được 1 cặp (i,j) như vậy ta được 1 xâu hoán vị của xâu ban đầu, lưu kết quả vào mảng kq theo thứ tự, đó là thứ tự từ điển của xâu ban đầu.

        Với n=9 thì thuật này chấp nhận được, tuy nhiên với n lớn hơn thì có thể cải tiến = quicksort và phương pháp tìm nhị phân để tìm cặp (i,j) thỏa.
        Don't depend too much on anyone in this world. Because even your shadow leaves you when you're in darkness.

        Comment


        • #5
          Em có thể nói rõ hơn cách cải tiến được không?
          University of Information Technology
          Cao Văn Nhàn _ CE10520355
          SĐT: 0188 403 4943

          Email: caovannhan2002@gmail.com

          Comment


          • #6
            code 1 bài cho zui )
            PHP Code:
            #include <iostream>
            #include <stdio.h>
            #include <conio.h>
            #include <string.h>
            using namespace std;
            //--------------
            int count=0;
            int n,Stop;
            char P[10];
            //--------------
            void Swap(char &achar &b)
            {
                
            char tg a;
                
            b;
                
            tg;
            }
            //---------------
            void sapxep(char a[])
            {
                for(
            int i n-1i++)
                    for(
            int j 1nj++)
                    {
                        if(
            a[i]>a[j])
                            
            Swap(a[i],a[j]);
                    }
            }
            //------------
            void Next_Hoanvi()  //Tim hoan vi ke tiep
            {
                
            int j,k,l,r;
                
            2;
                while (
            j>=&& P[j]>= P[j+1])    j--;
                if (
            == -1)
                    
            Stop 0;
                else
                {
                    
            1;
                    while (
            P[j] >= P[k]) k--;
                    
            Swap(P[j], P[k]);
                    
            1;
                    
            1;
                    while (
            r)
                    {
                        
            Swap(P[l], P[r]);
                        
            l++;
                        
            r--;
                    }
                }
            // end else
            }
            void Hoanvi()
            {
                
            Stop 1;
                while ( 
            Stop)
                {
                    
            count++;
                    
            cout<<endl<<P;
                    
            Next_Hoanvi();
                }
            }

            int main()
            {
                
            cin.ignore(0);
                
            cin.getline(P,10);
                
            strlen(P);
                
            sapxep(P);
                
            Hoanvi();
                
            cout<<endl<<count;
                return 
            0;

            Thuật toán cũng giống bạn quoctinvvn
            Last edited by 11520377; 10-07-2012, 15:59.

            Comment


            • #7
              Em cải tiến bài này như sau :
              - Phần sort lần đầu thì cài = quicksort, độ phức tạp giảm từ O(N^2) xuống còn O(NlogN)
              - Phần tìm cặp (i,j) : Nhận xét nếu xâu con từ vị trí X đến cuối xâu là một xâu không tăng theo thứ tự từ điển thì không tồn tại cặp (i,j) thỏa s[i] > s[j], i>j. Phương pháp ở đây là cần tìm được vị trí đầu tiên từ trái qua phải mà từ đó về cuối xâu là một xâu không tăng theo thứ tự từ điển. Giả sử vị trí tìm được là X, ta tiếp tục tìm từ 1->X-1 vị trí Y sao cho Y gần X nhất và tồn tại vị trí Z nằm trong đoạn X-> cuối xâu thỏa s[Y] < s[Z] sao cho s[Z] nhỏ nhất. Vị trí Y thì cho chạy từ X-1 về 1, với mỗi Y tìm trong X-> cuối xâu bằng phương pháp tìm nhị phân. Độ phức tạp ở đoạn này giảm từ O(N^2) xuống còn O(NlogN).

              Em mới nghĩ thế, chưa code thử
              Don't depend too much on anyone in this world. Because even your shadow leaves you when you're in darkness.

              Comment


              • #8
                Mình nghĩ cái này sẽ dễ hiểu hơn.
                Thuật toán sinh hoán vị kế tiếp của tập n phần tử
                2012-07-10_212439.jpg
                University of Information Technology
                Cao Văn Nhàn _ CE10520355
                SĐT: 0188 403 4943

                Email: caovannhan2002@gmail.com

                Comment


                • #9
                  Sao chưa thấy bài số 5 nhỉ?
                  University of Information Technology
                  Cao Văn Nhàn _ CE10520355
                  SĐT: 0188 403 4943

                  Email: caovannhan2002@gmail.com

                  Comment

                  LHQC

                  Collapse
                  Working...
                  X