nyoj 1078 汉诺塔(四)[二分图 || 规律 || 暴力 || 贪心]

题目:nyoj 1078 汉诺塔(四)

分析:做这个题目的时候是在图论的题目里面看到的,到时读了题目推了一下,发现好像有点规律,试了一下果然过了。

后来看了一下数据,才50,那么试了一下模拟,也过了。

好像zoj有一道题目卡模拟,模拟的时候必须贪心一下才能过

这道题出题人的意图在于考大家的:二分图最小路径覆盖。

把每一个球看做一个点,然后如果两个和为平方数的话就给这两个点之间连接一条边,然后用一个特殊的匹配算法,类似于匈牙利算法,但是每次找匹配的时候加入一条边上连接的有匹配的话就不能匹配,最后求一个最大匹配就好了。这个题目50个点,当然要预处理成离线的。

如果每次都建图跑的话时间复杂度是非常高的,所以我们可以用标记的方法,如果匹配过的就不用再匹配了。这样能降低很多时间,但是还是很长。

找规律代码:

#include <cstdio>
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 <cstdio>
#include <stack>
#include <cmath>
using namespace std;
stack<int> 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 <cstdio>
#include <stack>
#include <cmath>
#include <cstring>
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;j<i;j++)
            if(ok[i+j])
                mp[i][j]=true;
        tmp=Max_Pi(tmp,i);
        //printf("xx%d %d",i,tmp);
        ans[i-tmp]=i;
        if(i-tmp>55)
            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])){}
}
        
时间: 2024-12-17 12:15:05

nyoj 1078 汉诺塔(四)[二分图 || 规律 || 暴力 || 贪心]的相关文章

NYOJ 93 汉诺塔(三) 【栈的简单应用】

汉诺塔(三) 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描写叙述 在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候.在当中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔. 不论白天黑夜,总有一个僧侣在依照以下的法则移动这些金片:一次仅仅移动一片.无论在哪根针上.小片必须在大片上面.僧侣们预言.当全部的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中

NYOJ 93 汉诺塔(三)

汉诺塔(三) 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面.僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而

NYOJ 88 汉诺塔(一)(递归)

汉诺塔(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵 天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金 片:一次只移动一片,不管在哪根针上,小片必须在大片上面.僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消

nyoj 88 汉诺塔(一)【快速幂】

汉诺塔(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面.僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而

NYOJ 88 汉诺塔(一)

#include<stdio.h>const int max =1000000;long long kuaimi(int n){ long long temp=1; long long a=2; while(n>0) { if(n&1) temp=((temp*a)%max); a=((a*a)%max); n>>=1; } return temp;}int main(){ int num; scanf("%d\n",&num); whil

多柱汉诺塔最优算法

转自Florian 1. 三柱汉诺塔三柱汉诺塔是经典的汉诺塔问题,在算法设计中是递归算法的典型问题.其算法是这样的: 首先把A 柱上面的n- 1 个碟子通过C 柱移到B 柱上[T(n-1)步],然后把A 柱剩下的一个碟子移到C 柱上[1步], 最后把B 柱上所有的碟子通过A 柱移到C 柱上[T(n-1)步].很容易得到算法的递归方程为:T(n)=2*T(n-1)+1,因此,不难算出步数是T(n)=2^n-1.对于三柱汉诺塔的算法的正确性自然是毫无争议的,我们需要的是从三柱汉诺塔的设计中引申出多柱

算法笔记_013:汉诺塔问题(Java递归法和非递归法)

目录 1 问题描述 2 解决方案  2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus is possible for using animation. e.g. if n = 2 ; A→B ; A→C ; B→C; if n = 3; A→C ; A→B ; C→B ; A→C ; B→A ; B→C ; A→C; 翻译:模拟汉诺塔问题的移动规则:获得奖励的移动方法还是有可能的.

题解报告:hdu1995汉诺塔V

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1995 解题思路:求第k号盘子至少需要移动的次数,实际上是求n-k(认作是前g-1个盘子移动的总次数)个盘子(还欠一个)至少需要移动的次数再加上第(n-k+1)(认作是第g个盘子)个盘子移动一次即为移动的总次数 AC代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 int main() 5 {

hd 1207(四汉诺塔)

三个汉诺塔算法 f(n)=2^n-1 两个思路大同小异 Frame算法 在1941年,一位名叫J. S. Frame的人在<美国数学月刊>上提出了一种解决四柱汉诺塔问题的算法,这是人们熟知的Frame算法: (1)用4柱汉诺塔算法把A柱上部分的n- r个碟子通过C柱和D柱移到B柱上[F( n- r )步]. (2)用3柱汉诺塔经典算法把A柱上剩余的r个碟子通过C柱移到D柱上[2^r-1步]. (3)用4柱汉诺塔算法把B柱上的n-r个碟子通过A柱和C柱移到D柱上[F(n-r)步]. (4)依据上