程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> nyoj 1078 漢諾塔(四)[二分圖 || 規律 || 暴力 || 貪心]

nyoj 1078 漢諾塔(四)[二分圖 || 規律 || 暴力 || 貪心]

編輯:C++入門知識

nyoj 1078 漢諾塔(四)[二分圖 || 規律 || 暴力 || 貪心]


題目:nyoj 1078 漢諾塔(四)


分析:做這個題目的時候是在圖論的題目裡面看到的,到時讀了題目推了一下,發現好像有點規律,試了一下果然過了。


後來看了一下數據,才50,那麼試了一下模擬,也過了。

好像zoj有一道題目卡模擬,模擬的時候必須貪心一下才能過


這道題出題人的意圖在於考大家的:二分圖最小路徑覆蓋。

把每一個球看做一個點,然後如果兩個和為平方數的話就給這兩個點之間連接一條邊,然後用一個特殊的匹配算法,類似於匈牙利算法,但是每次找匹配的時候加入一條邊上連接的有匹配的話就不能匹配,最後求一個最大匹配就好了。這個題目50個點,當然要預處理成離線的。

如果每次都建圖跑的話時間復雜度是非常高的,所以我們可以用標記的方法,如果匹配過的就不用再匹配了。這樣能降低很多時間,但是還是很長。


找規律代碼:

 
#include 
int ans[55];
void isit()
{
    ans[1]=1,ans[2]=3;
    for(int i=3;i<51;i++)
        ans[i]=ans[i-1]+(i+1)/2 * 2;
}
int main()
{
    int T,n;isit();
    scanf("%d",&T);
    for(;T--&&scanf("%d",&n);printf("%d\n",ans[n]));
}
        


暴力代碼:

 
#include 
#include 
#include 
using namespace std;
stack st[60];
int ans[60];
void isit()
{
    int tmp=1,i=1;
    while(i<55)
    {
        int ok=0;
        for(i=1;!st[i].empty();i++)
        {
            int zhi = st[i].top()+tmp;
            int sq=sqrt(zhi);
            if(sq * sq == zhi)
            {
                st[i].push(tmp);
                ok=1;
                break;
            }
        }
        if(!ok){
            st[i].push(tmp);
            ans[i]=tmp-1;
        }
        tmp++;
    }
}
int main()
{
    int T,n;isit();
    scanf("%d",&T);
    for(;T--&&scanf("%d",&n);printf("%d\n",ans[n+1])){}
}
        


二分圖匹配代碼:

 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 60;
const int M = 1500;
int ans[N];
bool  ok[M*2+10];
bool mp[M][M];
int mx[M],my[M]; //mx保存正向邊 my保存反向邊
bool used[M]; //
bool dfs(int v) {
     for (int u = 1; u < v; ++u) //優化
         if (mp[v][u] && !used[u]) {
            used[u] = true;
             if (my[u] == -1 || dfs(my[u])) {  //一直向下找
                 my[u] = v;
                 mx[v] = u;
                 return true;
             }
         }
     return false;
}
int Max_Pi(int ans,int n)  //最大匹配
{
    for(int i=1;i<=n;i++)
    {
        if(mx[i]<0){
            memset(used,false,sizeof(used));
            if(dfs(i))
                ans++;
        }
    }
    return ans;
}
void Min_Road()  //最小路徑覆蓋
{
    memset(mx,-1,sizeof(mx)); //優化
    memset(my,-1,sizeof(my));
    for(int i=1;i*i<=2*M;i++)
        ok[i*i]=true;
    ans[1]=1;
    int tmp=0;
    for(int i=2;i<=M;i++)
    {
        for(int j=1;j55)
            break;
    }
//    for(int i=1;i<=50;i++)
//        printf("%d ",ans[i]);
}
int main()
{
    int T,n;Min_Road();
    scanf("%d",&T);
    for(;T--&&scanf("%d",&n);printf("%d\n",ans[n])){}
}
        


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved