USACO1.2 Name That Number 解题报告

这篇博客分享了作者在解决USACO1.2 Name That Number问题时的解题过程,从最初的顺序查找和递归全排列导致超时,到尝试二分查找仍然无法解决问题。最终,作者通过网上搜索找到了关键思路,即从字典出发匹配数字,优化了枚举方式,将复杂度降低到O(5000×12)。博客强调了枚举法在编程竞赛中的应用和思考问题的重要性,同时展示了实现该算法的简洁代码,标志着作者代码能力的提升。

解题思考顺序:

Attempt:很简单的把字典读进去了顺序查找,然后又很天真的把数字用递归进行了全排列,自己在本机上实验的结果很理想。。可是悲剧的就是严重超时!

Attempt:后来试着不用递归求出全排列,貌似还是很困难的。。卡住了很久很久。。至今没有编出来,还是代码能力不行

Attempt:我在别人的解题报告中也发现了有同样超时的问题,他也试过,二分查找字典也是很慢的,同样超时。。。

Final:经过网上搜索。。突然看到作者提示,从字典出发匹配数字。这也就是枚举的难点所在!

本题体现出了枚举的难点:枚举的方式

枚举的方法决定了这次大工程的耗时情况,比方说顺序查找算法复杂度为O(5000×3^12),二分查找的复杂度为O(3^12log5000)同样有一个3^12很大的系数。后来的方法只需要O(5000×12)的复杂度。

从这一点就可以看出有的题目可以使用枚举法,但是枚举的方式特殊,需要先思考问题,并且思考问题的时候要心里记得出其不意,正反思考!

下面贴出我的程序(这也是有史以来我感觉usaco最短的程序了):


/*
ID: ******
PROG: namenum
LANG: C++
*/
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<fstream>
using namespace std;
    FILE*fp;
    int map[100],len,flag,i,FLAG=0;
    char s[1000],t[1000];
int main()
{
    map['A']=2;map['B']=2;map['C']=2;map['D']=3;map['E']=3;map['F']=3;
    map['G']=4;map['H']=4;map['I']=4;map['J']=5;map['K']=5;map['L']=5;
    map['M']=6;map['N']=6;map['O']=6;map['P']=7;map['R']=7;map['S']=7;
    map['T']=8;map['U']=8;map['V']=8;map['W']=9;map['X']=9;map['Y']=9;
    fp=fopen("namenum.in","r");
    fscanf(fp,"%s",&s);
    len=strlen(s);
    ifstream cin("dict.txt");
    ofstream cout("namenum.out");
    while(cin>>t)
    {
        if(strlen(t)==len)
        {
            flag=1;
            for(i=0;i<len&&flag;i++)
                if(map[t[i]]!=s[i]-'0')
                    flag=0;
            if(flag==1)
            {
                FLAG=1;
                cout<<t<<endl;
            }
        }
    }
    if(FLAG==0)cout<<"NONE"<<endl;
    return 0;
}

经过最近的一些日子不断的刷题,代码能力增进不少,从以前的几行代码都要调试,到现在30行内的不用调试,值得我自己庆祝一下的。但是还有很大的发展空间,就像有篇文章里面所说,要达到100行以内不需要调试,还是有很大的差距的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值