PAT甲级考前整理(2019年3月备考)之一

    转载请注明出处:https://www.cnblogs.com/jlyg/p/7525244.html

      终于在考前,刷完PAT甲级131道题目,不容易!!!每天沉迷在刷题之中而不能超脱,也是一种境界。PAT甲级题目总的说卡题目的比较多,卡测试点的比较少,有些题目还会有题意混淆,这点就不吐槽了吧。静下心来耍这130道题,其实磨练的是一种态度与手感,养成的是一种习惯。热爱AC没有错!!(根据自己的刷题情况持续更新中,这次是第二遍刷了,发现换了新网站后,oj严格很多了,有些之前可以过的,现在已经不能过了)

  PAT甲级复习之二:主要写一些考前注意,以及常见算法。网址通道https://www.cnblogs.com/jlyg/p/10364696.html

  PAT甲级复习之三:主要是131题后的题目,网址通道https://www.cnblogs.com/jlyg/p/10364727.html

  131道题目主要的考点:

    1、排序:快速排序,直接插入排序,希尔排序,分治排序,堆排序。

    2、图论:拓扑排序(好像没考过)、最短路径、深度搜索、广度搜索。

    3、树:树的遍历、完全二叉树、AVL,CBT,BST。

    4、其他:并查集,模拟,哈希(二次探测一次,简单hash多次)、背包(一次),lcs(一次),最大子和(一次),set(一次),1057(分块搜索)

  主要算法:快排、直接插入排序、希尔排序、分治排序、堆排序、拓扑排序、dijkstra,floyd,dfs,bfs,AVL,并查集,树遍历算法。

  

  题目分类:

  1003(dfs or dijkstra)、1004(dfs)、1007(最长子和)、1010(二分查找)、1013(并查集)、1020(二叉树,前后序求广度)、1021(并查集)、1024(大数加法)、1029(归并排序)、1030(dikstra)、1043(前序判断是否是二叉收缩树)、1044(二分查找)、1045(lcs)、1053(dfs)、1063set)、1064(二叉搜索树)、1066(AVL)、1068(背包问题)、1076(bfs)、1078(hash二次探测)、1079(bfs,dfs)、1086(中前序求后序)、1089(排序)、1094(bfs or 并查集),1098(排序)、1099(BST)、1101(快排)、1102(反转二叉树)、1103(dfs剪枝)、1107(并查集)、1110(完全二叉树)、1111(dijkstra)、1114(并查集)、1115(BST)、1118(并查集)、1119(前后序求中序)、1123(AVL)、1127(bfs)、1130(dfs)




    dijkstra: 100310301111
    dfs:     10031004105310791103(dfs剪枝)、1130
    bfs:1076107910941127
    排序:1029(归并排序)、108910981101(快排)
    并查集:101310211094110711141118
    二叉树:1020(前后序求广度)、1043(前序判断是否是二叉搜索树)、1064(二叉搜索树)、1066(AVL)、1086(中前序求后序)、1099(BST)、1102(反转二叉树)、1110(完全二叉树)、1115(BST)、1119(前后序求中序)、1123(AVL)
    二分查找:10101044
    其他:1007(最长子和)、1024(大数加法)、1045(lcs)、1063set)、1068(背包问题)、1078(hash二次探测)
View Code

   错误修改:1013不是并查集,应该是dfs,刚刚发现,抱歉。

       1010这题目会比较奇怪,属于题意不清,第一可能会超出long long int,第二需要使用二分法不然超时,第三进制是无限制的可以是2到无限

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
long long int change(const char* strnum,long long int jinzhi)
{
    long long int len = strlen(strnum);
    long long int res = 0;
    for(long long int i=len-1,k=1;i>=0;--i,k*=jinzhi)
    {
        long long int a;
        if(strnum[i]>='0'&& strnum[i]<='9') a = strnum[i]-'0';
        else a = strnum[i]-'a'+10;
        res += k*a;
    }
    return res;
}

long long int Find_Radix(char* strnum,long long int dst,long long int left,long long int right)
{
    long long int mid = (left+right)/2;
    long long int midnum = change(strnum,mid);
    if(left==right)
    {
        if(dst != midnum) return -1;
        return left;
    }
    else if(left > right)
    {
        return -1;
    }
    if(midnum==dst)
    {
        return mid;
    }
    if(midnum<0||dst<midnum)
    {
        return Find_Radix(strnum,dst,left,mid-1);
    }
    else
    {
        return Find_Radix(strnum,dst,mid+1,right);
    }
}

int main()
{
    //freopen("test.txt","r",stdin);
    char s1[20],s2[20];
    int tag,jinzhi;
    scanf("%s%s%d%d",s1,s2,&tag,&jinzhi);
    if(tag==2)  {swap(s1,s2);}
    long long int a = change(s1,jinzhi);
    long long int left = 0;
    int len = strlen(s2);
    for(int i=0;i<len;++i)
    {
        long long int temp;
        if(s2[i]>='0'&&s2[i]<='9')
        {
            temp = s2[i]-'0';
        }
        else
        {
            temp = s2[i] - 'a'+10;
        }
        left = max(temp+1,left);
    }
    left = max((long long int)2,left);
    long long int right = max(a,left);
    long long int res = Find_Radix(s2,a,left,right);
    if(res==-1)
    {
        printf("Impossible
");
    }
    else
    {
        printf("%lld
",res);
    }
    return 0;
}
View Code

       1012题目排名是可以有并列的,比如有并列第1的情况。
       1014这道题的问题在于只要在17:00之前开始的就是正常的,结束时间是可以超过17:00后的,有点坑吧。

  1017模拟题,看代码和注释,很详细

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
int gettick(int h,int m,int s)
{
    return h*60*60+m*60+s;
}
const int window_starttime = gettick(8,0,0);
const int window_endtime = gettick(17,0,0);
struct Customer
{
    int cometime;   //来到时间
    int protime;    //处理时间,秒
};
int getfreewindow(int* windows,int k)
{
    int mintime = windows[0],mink = 0;
    for(int i=1;i<k;++i)
    {
        if(mintime > windows[i])
        {
            mink = i;
            mintime = windows[i];
        }
    }
    //注释1:该种情况就是,这个人是17点之前来的,但是前面有人结束后就已经是17点以后了,这种情况也不需要过滤,还是计算在内的。
    //if(mintime>window_endtime) return -1;
    return mink;
}
int cmp(const Customer& c1,const Customer& c2)
{
    return c1.cometime < c2.cometime;
}

int main()
{
    #ifdef ONLINE_JUDGE
    #else
        freopen("test.txt","r",stdin);
    #endif
    int n,k;
    scanf("%d%d",&n,&k);
    vector<Customer> vcus;
    for(int i=0;i<n;++i)
    {
        int h,m,s,p;
        scanf("%d:%d:%d%d",&h,&m,&s,&p);
        Customer cus;
        cus.cometime = gettick(h,m,s);
        cus.protime = min(60*p,60*60);
        if(cus.cometime <= window_endtime)      //过滤17点以后来的人
            vcus.push_back(cus);
    }
    n = vcus.size();
    sort(vcus.begin(),vcus.end(),cmp);
    int twaittime = 0/*总等待时间*/,cnt=0/*得到处理的人数*/,windowstime[k]/*该窗口空闲时间*/;
    for(int i=0;i<k;++i)
        windowstime[i] = window_starttime;
    for(int i=0;i<n;++i)
    {
        int iw = getfreewindow(windowstime,k);
        if(iw==-1) break;
        ++cnt;
        Customer &cus = vcus[i];
        if(cus.cometime<windowstime[iw])
        {
            twaittime+= (windowstime[iw]-cus.cometime);
            windowstime[iw] += cus.protime;
        }
        else
        {
            windowstime[iw] = cus.cometime + cus.protime;
        }
    }
    if(cnt==0) printf("0.0
");
    else printf("%.1lf
",1.0f*twaittime/cnt/60);
    return 0;
}
View Code

   1018题:dfs,求最小路径,若相同求最小借出的bike数,再若相同,求最小还回的bike数。要注意路径(cmax=10)PBM->(3)->(10),它的send为2,back为5,而不是send为0,back3(后面多出来的不能补到前面的,前面多出来的可以补到后面)

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
#define N (510)
const int INF = (1<<30);
int cmax,n,sp,m;
int cap[N];
int Len[N][N];
vector<int> Map[N];
bool bVis[N];
int minlen = INF;
int minsend = 0;
int minback= 0;
vector<int> minPath;
void dfs(int curI,int len,vector<int> path)
{
    if(curI==sp)
    {
        if(len <= minlen)
        {
            int curminsend = 0,curminback = 0;
            for(int i=1;i<path.size();++i)
            {
                int curcap = cap[path[i]];
                if(curcap<cmax/2)   //少了
                {
                    int adjust = cmax/2 - curcap;
                    if(adjust <= curminback)
                    {
                        curminback -= adjust;
                    }
                    else
                    {
                        adjust -= curminback;
                        curminback = 0;
                        curminsend += adjust;
                    }
                }
                else if(curcap>cmax/2)  //多了
                {
                    curminback += (curcap-cmax/2);
                }
            }
            if(len<minlen||(len==minlen&&curminsend<minsend)||
                (len==minlen&&curminsend==minsend&&curminback<minback))
            {
                minlen = len;
                minPath = path;
                minsend = curminsend;
                minback = curminback;
            }
        }
        return;
    }
    if(len >= minlen) return;
    for(int i=0;i<Map[curI].size();++i)
    {
        int nextI = Map[curI][i];
        if(!bVis[nextI])
        {
            bVis[nextI] = true;
            path.push_back(nextI);
            dfs(nextI,len+Len[curI][nextI],path);
            path.pop_back();
            bVis[nextI] = false;
        }
    }

}
int main()
{
    #ifdef ONLINE_JUDGE
    #else
        freopen("test.txt","r",stdin);
    #endif
    scanf("%d%d%d%d",&cmax,&n,&sp,&m);
    for(int i=0;i<=n;++i)
        for(int j=0;j<=n;++j)
            if(i==j) Len[i][j] = 0;
            else Len[i][j] = INF;
    for(int i=1;i<=n;++i)
        scanf("%d",&cap[i]);
    for(int i=0;i<m;++i)
    {
        int a,b,l;
        scanf("%d%d%d",&a,&b,&l);
        Len[a][b] = Len[b][a] = l;
        Map[a].push_back(b);
        Map[b].push_back(a);
    }
    bVis[0] = true;
    vector<int> path;
    path.push_back(0);
    dfs(0,1,path);
    printf("%d ",minsend);
    for(int i=0;i<minPath.size();++i)
    {
        if(i) printf("->");
        printf("%d",minPath[i]);
    }
    printf(" %d
",minback);
    return 0;
}
View Code


       1022题,需要用到整行输入字符串,而PAT的c++编译器是无法调用gets的,可以用fgets(buf,sizeof(buf),stdin);//读入的数据需要去掉 。如果在fgets函数之前调用了scanf,就必须要使用getchar把换行好读掉。

   当然也可以用 while(cin>>str)

        {
          char c;
          c=getchar();
          if(c==' ')    break;
        }
  
#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
void mygets(string& str)
{
    char temp[100];
    fgets(temp,sizeof(temp),stdin);
    temp[strlen(temp)-1] = '';
    str = temp;
}

map<string,set<int> > mapbname;
map<string,set<int> > mapauthor;
map<string,set<int> > mapkey;
map<string,set<int> > mappublisher;
map<string,set<int> >    mapyear;
struct Book
{
    int id;
    string bname;
    string author;
    string key;
    string publisher;
    string year;
    set<string> setkey;
    void Read()
    {
        scanf("%d",&id);
        getchar();
        mygets(bname);
        mygets(author);
        mygets(key);
        mygets(publisher);
        mygets(year);
        DealKey();
        mapbname[bname].insert(id);
        mapauthor[author].insert(id);
        mappublisher[publisher].insert(id);
        mapyear[year].insert(id);
    }
    void DealKey()
    {
        int len = key.length();
        string words = "";
        for(int i=0;i<len;++i)
        {
            if(key[i]!=' ') words += key[i];
            if(i==len-1||key[i]==' ')
            {
                if(!words.empty())
                {
                    setkey.insert(words);
                    mapkey[words].insert(id);
                }
                words = "";
            }
        }
        /*set<string>::iterator it = setkey.begin();
        for(;it!=setkey.end();it++)
            printf("%s
",it->c_str());
            */

    }
};
int main()
{
    #ifdef ONLINE_JUDGE
    #else
        freopen("test.txt","r",stdin);
    #endif
    int t;
    scanf("%d",&t);
    while(t--)
    {
        Book book;
        book.Read();
    }
    scanf("%d",&t);
    while(t--)
    {
        int opt;
        string str;
        scanf("%d: ",&opt);
        mygets(str);
        printf("%d: %s
",opt,str.c_str());
        map<string,set<int> > *mss = NULL;
        if(opt==1) mss = &mapbname;
        else if(opt==2) mss = &mapauthor;
        else if(opt==3) mss = &mapkey;
        else if(opt==4) mss = &mappublisher;
        else if(opt==5) mss = &mapyear;
        if(mss->find(str)!=mss->end())
        {
            set<int> &si = (*mss)[str];
            set<int>::iterator it = si.begin();
            for(;it!=si.end();it++)
            {
                printf("%07d
",*it);
            }
            if(si.size()==0) printf("Not Found
");
        }
        else
        {
            printf("Not Found
");
        }
    }
    return 0;
}
View Code
  1024题:输入本身就是回文串时,直接输出该回文串,并且输出步数为0.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
#define N (100)
bool isPal(char* str)
{
    int l = strlen(str);
    for(int i=0;i<l/2;++i)
        if(str[i] != str[l-i-1]) return false;
    return true;
}
void Add(char* str)
{
    char temp[N];
    int iAdd = 0;
    int l = strlen(str);
    int tlen = 0;
    for(int i=0;i<l;++i)
    {
        int res = str[i]-'0'+str[l-i-1]-'0' +iAdd;
        temp[tlen++] = res%10 + '0';
        iAdd = res/10;
    }
    if(iAdd) temp[tlen++] = iAdd + '0';
    temp[tlen] = '';
    string strTemp = temp;
    reverse(strTemp.begin(),strTemp.end()); //反转
    strcpy(str,strTemp.c_str());
}
int main()
{
    char strNum[N];
    int k;
    scanf("%s%d",strNum,&k);
    int step = 0;
    while(!isPal(strNum)&&step<k)
    {
        Add(strNum);
        ++step;
    }
    printf("%s
",strNum);
    printf("%d
",step);
    return 0;
}
View Code

      1026题:题目比较坑:

    1、处理时间有超过2个小时的,需要自己代码判断大于2个小时,变成两个小时。

    2、21:00:00之后不处理,包括21点整。

    3、当有普通球台和VIP球台时,VIP客户遵循选择最小编号的VIP球台,而非编号最小的普通球台;普通客户遵循选择最小的球台

    4、四舍五入,不然最后一个case过不了。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
#define N (10010)
int getTick(int h,int m,int s)
{
    return 60*60*h+60*m+s;
}
const int SartTime = getTick(8,0,0);
const int EndTime = getTick(21,0,0);
bool bTableVip[N];
int  tableperson[N];        //每张桌子处理的人数
int  tabfreetime[N];        //每张桌子空闲时间
int tables;     //桌子数
struct Custom
{
    int arrivingtime;       //到达时间
    int servingtime;        //开始服务时间
    int playingtime;           //玩耍时间
};
int getFreeTable(int& freeviptableid) //该函数返回一个编号最小,最早空闲时间的桌子编号,freeviptable表示vip中编号最小的,最早空闲时间的桌子编号
{
    int tablesid = -1,mintime = getTick(30,0,0),minviptime=getTick(30,0,0);
    freeviptableid = -1;
    for(int i=1;i<=tables;++i)
    {
        if(tabfreetime[i]<mintime)
        {
            mintime = tabfreetime[i];
            tablesid = i;
        }
        if(bTableVip[i]&&tabfreetime[i]<minviptime)
        {
            minviptime = tabfreetime[i];
            freeviptableid = i;
        }
    }
    return tablesid;
}
bool cmp(const Custom& c1,const Custom& c2)
{
    return c1.arrivingtime < c2.arrivingtime;
}
bool cmp2(const Custom& c1,const Custom& c2)
{
    return c1.servingtime < c2.servingtime;
}
void printtime(int tick)
{
    printf("%02d:%02d:%02d ",tick/3600,tick%3600/60,tick%60);
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("test.txt","r",stdin);
    #endif // ONLINE_JUDGE
    int n;
    scanf("%d",&n);
    vector<Custom>cus,cusvip;
    for(int i=0;i<n;++i)
    {
        Custom c;
        int h,m,s,bVip;
        scanf("%d:%d:%d%d%d",&h,&m,&s,&c.playingtime,&bVip);
        c.arrivingtime = getTick(h,m,s);
        c.playingtime = min(2*60*60,c.playingtime*60);    //转换成秒
        if(bVip) cusvip.push_back(c);
        else cus.push_back(c);
    }
    //加入末尾哨兵,这样当下面运用是不需要考虑vector为空的时候
    Custom finalcus;
    finalcus.arrivingtime = getTick(30,0,0);
    cus.push_back(finalcus);
    cusvip.push_back(finalcus);
    sort(cus.begin(),cus.end(),cmp);
    sort(cusvip.begin(),cusvip.end(),cmp);
    int m;
    scanf("%d%d",&tables,&m);
    for(int i=0;i<m;++i)
    {
        int tableid;
        scanf("%d",&tableid);
        bTableVip[tableid] = 1;
    }
    for(int i=0;i<tables;++i) tabfreetime[i+1] = SartTime;
    vector<Custom> res;
    for(int i=0;i<n;++i)
    {
        int freeviptableid;
        int freetableid = getFreeTable(freeviptableid);
        Custom curcus;
        if(cusvip[0].arrivingtime<cus[0].arrivingtime||     /*当vip用户早到时,vip用户肯定先上桌*/
           bTableVip[freetableid]&&cusvip[0].arrivingtime<=tabfreetime[freetableid])  /*如果vip用户晚到,但是这桌是vip专用桌,此时要看vip到达时间是否在桌有空之前到达*/
        {
            curcus = cusvip[0];
            cusvip.erase(cusvip.begin());
            if(freeviptableid!=-1&&curcus.arrivingtime>=tabfreetime[freeviptableid])    //vip用户来的比最小vip桌空闲时间晚,这个时候前面即使有空闲普通桌,也要选择vip桌。
                freetableid = freeviptableid;
        }
        else
        {
            curcus = cus[0];
            cus.erase(cus.begin());
        }
        if(tabfreetime[freetableid]>=EndTime||curcus.arrivingtime>=EndTime)
        {
            break;
        }
        curcus.servingtime = max(tabfreetime[freetableid],curcus.arrivingtime);
        tabfreetime[freetableid] = curcus.servingtime + curcus.playingtime;
        ++tableperson[freetableid];
        res.push_back(curcus);
    }
    sort(res.begin(),res.end(),cmp2);
    for(int i=0;i<res.size();++i)
    {
        printtime(res[i].arrivingtime);
        printtime(res[i].servingtime);
        int waittime = max(0,res[i].servingtime - res[i].arrivingtime);
        waittime = (int)(1.0*waittime/60+0.5);
        printf("%d
",waittime);
    }
    for(int i=1;i<=tables;++i)
    {
        if(i-1) printf(" ");
        printf("%d",tableperson[i]);
    }
    printf("
");
    return 0;
}
View Code

      1029题:坑点,内存超出限制,找到中位数之后,就无需再继续往队列中push。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
#include<iterator>
#include<queue>
using namespace std;
#define N (2*100000+1)
#define INF (1<<30)

queue<int> a;
queue<int> b;
int main()
{
    int n,m;
    scanf("%d",&n);
    for(int i=0;i<n;++i)
    {
        int temp;
        scanf("%d",&temp);
        a.push(temp);
    }
    a.push(INF);
    scanf("%d",&m);
    int iCnt = 0;
    int iMid = -1;
    for(int i=0;i<m;++i)
    {
        int temp;
        scanf("%d",&temp);
        if(iMid == -1)
        {
            b.push(temp);
            if(iCnt==(m+n+1)/2-1)
            {
                iMid = min(a.front(),b.front());
            }
            if(a.front()<b.front()) a.pop();
            else b.pop();
        }
        ++iCnt;
    }
    b.push(INF);
    for(;iCnt<=(m+n+1)/2-1;++iCnt)
    {
        iMid = min(a.front(),b.front());
        if(a.front()<b.front()) a.pop();
        else b.pop();
    }
    printf("%d
",iMid);
    return 0;
}
View Code

   用数组的做法,类似分治排序的方法(可以看算法导论中对分治排序的讲解,写的特别好!!)

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("1.txt","r",stdin);
    #endif // ONLINE_JUDGE
    int n1,n2;
    scanf("%d",&n1);
    int a1[n1+1];
    for(int i=0;i<n1;++i)
        scanf("%d",&a1[i]);
    scanf("%d",&n2);
    int res = 0,k=0,j=0;
    for(int i=0;i<n2;++i)
    {
        int num;
        scanf("%d",&num);
        while(a1[j]<num&&k<(n1+n2+1)/2)
        {
            res = a1[j++];
            k++;
        }
        if(a1[j]>=num&&k<(n1+n2+1)/2)
        {
            res = num;
            k++;
        }
    }
    //这一行容易忘记,因为k可能没有到中位数。
    while(k++<(n1+n2+1)/2)
        res = a1[j++];
    printf("%d
",res);
    return 0;
}
View Code

  1031题:坑点,当字符串长度是9的时候,试试,比如123456789,正确输出是,计算 n2 = (N+2+2)/3,而不是n2=(N+2)/3;这种算出来n2可能会比n1,n3小

      

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>

using namespace std;
int main()
{
    char str[100];
    //while(true)
    {
        scanf("%s",str);
        int len = strlen(str);
        int n1,n2,n3 = (len+2+2)/3;
        n3 = max(3,n3);
        for(;n3<=len;++n3)
            if((len+2-n3)%2==0)
                break;
        int space = n3-2;
        n1 = n2 = (len - n3 + 2)/2;
        for(int i=0;i<n1-1;++i)
        {
            printf("%c",str[i]);
            for(int j=0;j<space;++j)
                printf(" ");
            printf("%c
",str[len-i-1]);
        }
        printf("%c",str[n1-1]);
        for(int i=n1;i<n1+space;++i)
            printf("%c",str[i]);
        printf("%c
",str[n1-1+n3-1]);
    }

    return 0;
}
View Code

        1032题:坑点,当搜索的两个起点是一样的时候测试点 。个人觉得应该还要考虑两个起点是直接父子关系的情况(但是测试点中没有。。。)

        

1 1 3
1 c 2
2 a 3
3 b -1
#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;
#define N (100000+10)
vector<int> vcPath[N];
bool bVis[N] = {0};
int iComPos = -1;
void dfs(int iCurI)
{     
    bVis[iCurI] = true;
    for(int i=0;i<vcPath[iCurI].size();++i)
    {
        int iNextI = vcPath[iCurI][i];
        if(false==bVis[iNextI])
            dfs(iNextI);
        else
        {
            iComPos = iNextI;
            return;
        }
    }
}
int main()
{
    int s1,s2,n;
    scanf("%d%d%d",&s1,&s2,&n);
    if(s1 == s2) iComPos = s1;
    for(int i=0;i<n;++i)
    {
        int a,b;
        char c[10];
        scanf("%d%s%d",&a,c,&b);
        if(s1 == a && s2 == b || s2==a&&s1==b)
        {
            iComPos = b;    
        }
        if(b != -1)
        {
            vcPath[a].push_back(b);
        }
    }    
    if(-1 == iComPos)
    {
        dfs(s1);
        dfs(s2);
    }
    if(-1==iComPos) printf("%d
",-1);
    else printf("%05d
",iComPos);
    return 0;
}
/*
1 2 2
1 c 2
2 a -1
*/
View Code

       1033题:坑点2:1)终点可能是起点,2)如果当前加油点可以直接开到终点,并且后面几个点都比他大的话,就无需遍历接来的点了(这题是真的很烦。。。。目测不是考试原题,仅仅是练习题)

  1)寻找必须要加油的站点加入到set中,搜索距离为dis的站点+满油时行驶距离之内的所有站点,找最近的比dis单价便宜的站点,如果没有,则找这段距离中价格最便宜的。

  2)根据set中的判断这次的加油站价格是否比下一个加油站的价格小,如果是,则加满油,否则加的油能够支持到下一个加油站就行了。

  解法1:第二点需要特殊处理

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;

int main()
{
    int iCmax,d,davg,n;
    scanf("%d%d%d%d",&iCmax,&d,&davg,&n);
    map<int,double> mis;
    for(int i=0;i<n;++i)
    {
        double p;
        int iDis;
        scanf("%lf%d",&p,&iDis);
        if(iDis >= d) continue;
        if(mis.find(iDis)==mis.end())
            mis[iDis] = p;
        else
            if(mis[iDis]>p) mis[iDis] = p;
    }
    if(mis.size()==0||mis.begin()->first!=0)    //一个测试点
    {
        printf("The maximum travel distance = 0.00
");
    }
    else if(d==0)    //没有测试点
    {
        printf("0.00
");
    }
    else
    {
        double iMaxLen = iCmax*davg;
        map<int,double>::iterator it = mis.begin();
        set<int> si;
        while(it!=mis.end()&&it->first < d)
        {
            map<int,double>::iterator tit = it;
            si.insert(it->first);
            double fDis = it->first;
            double fPrice = it->second;
            double fMinPrice = -1;
            double fMinDis = -1;
            //如果当前加油点可以直接开到终点,并且后面几个点都比他大的话,就无需遍历接来的点了
            bool bBreak = true;
            if(fDis+iMaxLen>=d)
            {
                for(;tit!=mis.end();++tit)
                {
                    if(tit->second < fPrice)
                    {
                        bBreak = false;
                        break;
                    }
                }
                if(bBreak) break;
            }

            tit = it;
            while(++tit != mis.end())
            {
                if(tit->first - fDis <= iMaxLen && tit->first < d)
                {
                    if(fMinDis == -1 || fMinPrice > tit->second)
                    {
                        fMinDis = tit->first;
                        fMinPrice = tit->second;
                        if(fMinPrice < fPrice)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    break;
                }
            }
            tit = mis.find(fMinDis);
            if(tit != it)
            {
                it = tit;
            }
            else break;
        }
        set<int>::iterator sit = si.begin();
        double fTotal = 0;
        double fCurCap = 0;
        for(int i=0;sit != si.end();sit++,++i)
        {
            if(i == si.size()-1)
            {
                if(*sit+iMaxLen < d)
                {
                    printf("The maximum travel distance = %.2lf
",*sit+iMaxLen);
                }
                else
                {
                    //printf("gas=%.2lf
",1.0*(d-*sit)/davg-fCurCap);
                    fTotal += (1.0*(d-*sit)/davg-fCurCap)*mis[*sit];
                    printf("%.2lf
",fTotal);
                }
            }
            else
            {
                set<int>::iterator nextsit = sit;
                ++nextsit;
                if(mis[*nextsit] > mis[*sit])
                {
                    //printf("gas=%.2f
",iCmax-fCurCap);
                    fTotal += 1.0*(iCmax-fCurCap)*mis[*sit];
                    fCurCap = iCmax - 1.0*(*nextsit-*sit)/davg;
                }
                else
                {
                    //printf("gas=%.2f
",(*nextsit-*sit)/davg-fCurCap);
                    fTotal += (1.0*(*nextsit-*sit)/davg-fCurCap)*mis[*sit];
                    fCurCap = 0;
                }
            }
            //printf("[%d %.2f]
",*sit,fTotal);
        }
    }
    return 0;
}
View Code

  解法2:把终点看作一个加油站,油价为0,则无需再考虑第二点

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;

int main()
{
    int iCmax,d,davg,n;
    scanf("%d%d%d%d",&iCmax,&d,&davg,&n);
    map<int,double> mis;
    for(int i=0;i<n;++i)
    {
        double p;
        int iDis;
        scanf("%lf%d",&p,&iDis);
        if(iDis >= d) continue;
        if(mis.find(iDis)==mis.end())
            mis[iDis] = p;
        else
            if(mis[iDis]>p) mis[iDis] = p;
    }
    mis[d] = 0;
    if(d&&mis.size()==1||mis.begin()->first!=0)    //一个测试点
    {
        printf("The maximum travel distance = 0.00
");
    }
    else if(d==0)    //没有测试点
    {
        printf("0.00
");
    }
    else
    {
        double iMaxLen = iCmax*davg;
        map<int,double>::iterator it = mis.begin();
        set<int> si;
        while(it!=mis.end())
        {
            map<int,double>::iterator tit = it;
            si.insert(it->first);
            double fDis = it->first;
            double fPrice = it->second;
            double fMinPrice = -1;
            double fMinDis = -1;
            while(++tit != mis.end())
            {
                if(tit->first - fDis <= iMaxLen)
                {
                    if(fMinDis == -1 || fMinPrice > tit->second)
                    {
                        fMinDis = tit->first;
                        fMinPrice = tit->second;
                        if(fMinPrice < fPrice)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    break;
                }
            }
            tit = mis.find(fMinDis);
            if(tit != it)
            {
                it = tit;
            }
            else break;
        }
        set<int>::iterator sit = si.begin();
        double fTotal = 0;
        double fCurCap = 0;
        for(int i=0;sit != si.end();sit++,++i)
        {
            if(i == si.size()-1)
            {
                if(*sit+iMaxLen < d)
                {
                    printf("The maximum travel distance = %.2lf
",*sit+iMaxLen);
                }
                else
                {
                    //printf("gas=%.2lf
",1.0*(d-*sit)/davg-fCurCap);
                    fTotal += (1.0*(d-*sit)/davg-fCurCap)*mis[*sit];
                    printf("%.2lf
",fTotal);
                }
            }
            else
            {
                set<int>::iterator nextsit = sit;
                ++nextsit;
                if(mis[*nextsit] > mis[*sit])
                {
                    //printf("gas=%.2f
",iCmax-fCurCap);
                    fTotal += 1.0*(iCmax-fCurCap)*mis[*sit];
                    fCurCap = iCmax - 1.0*(*nextsit-*sit)/davg;
                }
                else
                {
                    //printf("gas=%.2f
",(*nextsit-*sit)/davg-fCurCap);
                    fTotal += (1.0*(*nextsit-*sit)/davg-fCurCap)*mis[*sit];
                    fCurCap = 0;
                }
            }
            //printf("[%d %.2f]
",*sit,fTotal);
        }
    }
    return 0;
}
View Code

  1034题:用dfs题来做,我把名字转换成数字的时候刚开始弄错了死活2个case没过去((str[0]-'A')+(str[1]-'A')*26+(str[2]-'A')*26*26;)其实正确的是((str[2]-'A')+(str[1]-'A')*26+(str[0]-'A')*26*26;)不然用map或者set默认排序时会有问题。

  

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<string>
#include<iterator>
using namespace std;
#define N (26*26*26+10)
int n,k;
int val[N] = {0};
bool bVis[N] = {1};
vector<int> vcMap[N];
map<int,int> Res;
int GetNum(char* str)
{
    return (str[2]-'A')+(str[1]-'A')*26+(str[0]-'A')*26*26;
}
string GetStr(int num)
{
    char str[4] = {0};
    str[2] = num%26+'A';
    str[1] = num/26%26+'A';
    str[0] = num/26/26+'A'; 
    return str;
}
int iMaxCnt = 0,iMaxI = 0,iMaxMin = 0;
void dfs(int curI)
{
    bVis[curI] = true;
    ++iMaxCnt;
    iMaxMin += val[curI];
    if(val[iMaxI] < val[curI]) iMaxI = curI; 
    for(int i=0;i<vcMap[curI].size();++i)
    {
        int NextI = vcMap[curI][i];
        if(!bVis[NextI])
            dfs(NextI); 
    }
}
int main()
{
    scanf("%d%d",&n,&k);
    int iMaxN = 0;
    for(int i=0;i<n;++i)
    {
        char s1[4],s2[4];
        int m;
        scanf("%s%s%d",s1,s2,&m);
        int ia = GetNum(s1),ib=GetNum(s2);
        val[ia] += m;
        val[ib] += m;
        bVis[ia] = false;
        bVis[ib] = false;
        vcMap[ia].push_back(ib);
        vcMap[ib].push_back(ia);
        iMaxN = max(iMaxN,max(ia,ib));
    }
    for(int i=0;i<=iMaxN;++i)
    {
        if(!bVis[i])
        {
            iMaxCnt = 0,iMaxI = i,iMaxMin = 0;
            dfs(i);
            if(iMaxCnt > 2 && iMaxMin>2*k)
            {
                Res[iMaxI] = iMaxCnt;
            }
        }
    }
    printf("%d
",Res.size());
    map<int,int>::iterator it = Res.begin();
    for(;it!=Res.end();it++)
        printf("%s %d
",GetStr(it->first).c_str(),it->second);
    return 0;
}
View Code

       1035题:注意输出是单数是 is 1 account ,双数是 are N accounts;

     1038题:通过sort排序,比较方法是s1+s2,s2+s1判断谁小就好了。输出的时候考虑前面的0去掉,2 0 00 别输出是00,但是后面的0不能去掉了(刚开始我就把后面的0也去掉了)比如3 00 01 001我的输出是11(这是错的)

  

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int cmp(const string& s1,const string& s2)
{
    string temp1 = s1 + s2;
    string temp2 = s2 + s1;
    for(int i=0;i<temp1.length();++i)
    {
        if(temp1[i] != temp2[i])
            return temp1[i] - temp2[i] < 0;
    }
    return 1;
}
int main()
{
    //while(true)
    {
        vector<string> vs;
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;++i)
        {
            char str[10];
            scanf("%s",str);
            vs.push_back(str);        
        }
        sort(vs.begin(),vs.end(),cmp);
        bool bFirst = true;
        for(int i=0;i<vs.size();++i)
        {
            if(bFirst)
            {
                int a = atoi(vs[i].c_str());
                if(a==0 && i!= vs.size()-1) continue;
                printf("%d",a);    
                bFirst = false;
            }
            else
            {
                printf("%s",vs[i].c_str());
            }        
        }
        printf("
");
    }
    
    return 0;
}
View Code

   1044题:如果暴力会超时,主要代码中的bCanBreak的判断,当里层循环遍历到最后一个数字的时候,就直接跳出大循环。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
#define INF (1<<30)
vector<int> vc;
map<int,int> res;
map<int,int> res2;
int main()
{
    int n,dst;
    scanf("%d%d",&n,&dst);
    for(int i=0;i<n;++i)
    {
        int a;
        scanf("%d",&a);
        vc.push_back(a);
    }
    int iMin = INF;
    bool bCanBreak = false;
    for(int i=0;i<n;++i)
    {
        int sum = 0;
        for(int j=i;j<n;++j)
        {
            sum += vc[j];
            if(sum == dst)
            {
                res[i+1] = j+1;
                break;
            }
            else if(sum > dst)
            {
                if(iMin > sum)
                {
                    iMin = sum;
                    res2.clear();
                }
                if(iMin == sum)
                {
                    res2[i+1] = j+1;
                }
                break;
            }
            if(j==n-1) bCanBreak = true;
        }
        if(bCanBreak) break;
    }
    if(res.size())
    {
        map<int,int>::iterator it = res.begin();
        for(;it != res.end();it++)
            printf("%d-%d
",it->first,it->second);
    }
    else
    {
        map<int,int>::iterator it = res2.begin();
        for(;it != res2.end();it++)
            printf("%d-%d
",it->first,it->second);
    }
    return 0;
}
View Code

   二刷的时候用的方法:计算res等于从第i个加到j个。然后每次减去第i个,发现res小于寻找的数时,加上j+1,j+2直到res>=寻找的数,然后重复以上步骤。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<climits>
#include<iterator>
using namespace std;
#define N (100010)
int n,m;
int a[N];
int minM = INT_MAX;
void print(int needm)
{
    int res = 0;
    for(int i=0,j=0;i<n;++i)
    {
        while(res < needm&&j<n)
            res += a[j++];
        if(res == needm)
        {
            printf("%d-%d
",i+1,j);
            minM = needm;
        }
        else if(minM!=needm&&res>needm&&res<minM)
            minM = res;
        res -= a[i];
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("1.txt","r",stdin);
    #endif // ONLINE_JUDGE

    scanf("%d%d",&n,&m);

    for(int i=0;i<n;++i)
        scanf("%d",&a[i]);
    print(m);
    if(minM!=m)
    {
        print(minM);
    }
    return 0;
}
View Code

  1045题:变异的lcs,卡了一下

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define N (210)

int main()
{
    int n;
    bool bHave[N] = {false};
    int m,l,love[N];
    vector<int> vcColor;
    scanf("%d
",&n);
    scanf("%d",&m);
    for(int i=0;i<m;++i)
    {
        scanf("%d",&love[i]);
        bHave[love[i]] = true;
    }
    scanf("%d",&l);
    for(int i=0;i<l;++i)
    {
        int a;
        scanf("%d",&a);
        if(bHave[a])
            vcColor.push_back(a);
    }
    n = vcColor.size();
    int dp[m+1][n+1];
    memset(dp,0,sizeof(dp));
    for(int i=0;i<m;++i)
        for(int j=0;j<n;++j)
        {
            if(love[i]==vcColor[j])
            {
                dp[i+1][j+1] = max(dp[i+1][j]+1,dp[i][j] + 1);
            }
            else
            {
                dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j]);
            }
        }
    printf("%d
",dp[m][n]);
    return 0;
}
View Code

   1046题:如果是记录每个点到下一个点的距离,然后用累加法会超时,应该是记录每个点到起点的距离,然后相减就是他们之间的距离。同时要注意,假设a<b,a到b的距离有两种可能性,一种是a到b,另一种是b到终点,然后在到a。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;

#define N (100010)

int main()
{
    int dis[N];
    int n;
    scanf("%d",&n);
    int len = 0;
    for(int i=0;i<n;++i)
    {
        int a;
        scanf("%d",&a);
        len += a;
        dis[i+1] = len;
    }
    int m;
    scanf("%d",&m);
    while(m--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(a > b) swap(a,b);
        int l = 0;
        if(a != b)
        {
            l = dis[b-1] - dis[a-1];
        }
        l = min(l,len-l);
        printf("%d
",l);
    }
    return 0;
}
View Code

  1047题:不能用set存储,最后一个case会超时,由于set每一次插入都会排一次序,使用vector来存储,然后输入结束后排一次序就可以了

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<string>
#include<iterator>
using namespace std;
#define N (40010)
#define K (2510)

int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    vector<string> Course[k+1];
    for(int i=0;i<n;++i)
    {
        char name[5];
        int m;
        scanf("%s%d",name,&m);
        for(int j=0;j<m;++j)
        {
            int c;
            scanf("%d",&c);
            Course[c].push_back(name);
        }
    }
    for(int i=1;i<=k;++i)
    {
        printf("%d %d
",i,Course[i].size());
        if(Course[i].size())
        {
            sort(Course[i].begin(),Course[i].end());
        }
        for(int j=0;j<Course[i].size();++j)
        {
            printf("%s
",Course[i][j].c_str());
        }
    }
    return 0;
}
View Code

  1048题:面值可能会相等,比如 2 14 7 7输出是 7 7

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<climits>
#include<iterator>
using namespace std;
#define N (100010)
int Hash[N];
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("1.txt","r",stdin);
    #endif // ONLINE_JUDGE
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i)
    {
        int a;
        scanf("%d",&a);
        ++Hash[a];
    }
    for(int i=0;i<=m;++i)
    {
        if(Hash[i]&&Hash[m-i])
        {
            if(i==m-i&&Hash[i]==1) continue;
            printf("%d %d
",i,m-i);
            return 0;
        }
    }
    printf("No Solution
");
    return 0;
}
View Code

   1052题:dfs,有一个坑点,当起点是一个在图中的值时,输出一个是 0 -1;

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
#define N (100010)
struct Node
{
    int addr;
    int key;
    int nextaddr;
    Node()
    {
        nextaddr = -1;
        addr = -1;
    }
};

Node Map[N];
vector<Node> vc;
int n,iStart;
void dfs(int CurI)
{
    if(CurI == -1 || Map[CurI].addr==-1) return;
    Node curnode = Map[CurI];
    vc.push_back(curnode);
    dfs(curnode.nextaddr);
}
int cmp(const Node& n1,const Node& n2)
{
    return n1.key - n2.key < 0;
}
int main()
{
    scanf("%d%d",&n,&iStart);
    for(int i=0;i<n;++i)
    {
        Node node;
        scanf("%d%d%d",&node.addr,&node.key,&node.nextaddr);
        Map[node.addr] = node;
    }
    dfs(iStart);
    sort(vc.begin(),vc.end(),cmp);
    int nVcSize = vc.size();
    printf("%d",nVcSize);
    if(nVcSize) printf(" %05d",vc[0].addr);
    else printf(" -1");
    printf("
");
    for(int i=0;i<nVcSize;++i)
    {
        printf("%05d %d ",vc[i].addr,vc[i].key);
        if(i != nVcSize-1)
        {
            printf("%05d
",vc[i+1].addr);
        }
        else printf("-1
");
    }
    return 0;
}
View Code

  1053题:简单题,dfs,使用vector<vector<int> >存储答案路径,使用vector<int>[]存储图,然后在叶子节点加上一个结束节点,方便判断。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
#define N (110)
int w[N]={0};
int n,m,s;
vector<int> vcMap[N];
vector<vector<int> > vcPath;
void dfs(int CurI,int tw,vector<int> vc)
{
    if(CurI==n)
    {
        if(tw == s)
        {
            vcPath.push_back(vc);
        }
       return;
    }
    vc.push_back(w[CurI]);
    for(int i=0;i<vcMap[CurI].size();++i)
    {
        int NextI = vcMap[CurI][i];
        dfs(NextI,tw+w[CurI],vc);
    }
    vc.pop_back();
}
int cmp(const vector<int>& v1,const vector<int>& v2)
{
    for(int i=0;i<v1.size()&&i<v2.size();++i)
    {
        if(v1[i] != v2[i])
            return v1[i]-v2[i] > 0;
    }
    return 0;
}
int main()
{

    scanf("%d%d%d",&n,&m,&s);
    for(int i=0;i<n;++i)
        scanf("%d",&w[i]);
    for(int i=0;i<m;++i)
    {
        int a,k,b;
        scanf("%d%d",&a,&k);
        for(int j=0;j<k;++j)
        {
            scanf("%d",&b);
            vcMap[a].push_back(b);
        }
    }
    //方便判断结束
    for(int i=0;i<n;++i)
        if(vcMap[i].size()==0) vcMap[i].push_back(n);
    vector<int> vc;
    dfs(0,0,vc);
    sort(vcPath.begin(),vcPath.end(),cmp);
    for(int i=0;i<vcPath.size();++i)
    {
        vector<int> &vc2 = vcPath[i];
        bool bFirst = true;
        for(int j=0;j<vc2.size();++j)
        {
            if(bFirst) bFirst = false;
            else printf(" ");
            printf("%d",vc2[j]);
        }
        printf("
");
    }
    return 0;
}
View Code

    1055题:之前由于每次查询都去排序导致超时,傻了

  

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
struct ST
{
    char name[10];
    int age;
    int net;
};
int cmp(const ST& st1,const ST& st2)
{
    if(st1.net != st2.net) return st1.net-st2.net > 0;
    if(st1.age != st2.age) return st1.age - st2.age < 0;
    return strcmp(st1.name,st2.name)<0;

}
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    vector<ST> vc;
    for(int i=0;i<n;++i)
    {
        ST st;
        scanf("%s%d%d",st.name,&st.age,&st.net);
        vc.push_back(st);
    }
    sort(vc.begin(),vc.end(),cmp);

    for(int i=0;i<k;++i)
    {
        int m,amin,amax;
        scanf("%d%d%d",&m,&amin,&amax);
        printf("Case #%d:
",i+1);
        int iCnt = 0;
        for(int i=0;i<vc.size();++i)
        {
            if(iCnt == m)
            {
                break;
            }
            if(amin<=vc[i].age&&vc[i].age<=amax)
            {
                printf("%s %d %d
",vc[i].name,vc[i].age,vc[i].net);
                ++iCnt;
            }
        }
        if(iCnt==0)
            printf("None
");
    }
    return 0;
}
View Code

  1056题:不难,题目比较难理解:大致题意有np个老鼠,每次nc只一组选出最大的,最后不满nc的算一组。反复,直到求得最大质量的老鼠。第二行输入表示从0到np的老鼠质量,第三行输入表示第几只老鼠。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
struct ST
{
    int i;
    int w;
    int iRank;
};
int cmp(const ST& st1,const ST& st2)
{
    return st1.i-st2.i<0;
}
int main()
{
    int np,nc;
    scanf("%d%d",&np,&nc);
    int w[np];
    ST st[np];
    vector<ST*> vc;
    vector<vector<ST*> > vcRes;
    for(int i=0;i<np;++i)
        scanf("%d",&w[i]);
    for(int i=0;i<np;++i)
    {
        scanf("%d",&st[i].i);
        st[i].w = w[st[i].i];
        vc.push_back(&st[i]);
    }
    while(vc.size()>1)
    {
        vector<ST*> vcTemp = vc;
        vc.clear();
        int i=0;
        vector<ST*> oneRes;
        while(i<vcTemp.size())
        {
            ST* bigone = NULL;
            for(int j=0;j<nc&&i<vcTemp.size();++j,++i)
            {
                if(bigone==NULL)
                {
                    bigone = vcTemp[i];
                }
                else if(bigone->w < vcTemp[i]->w)
                {
                    oneRes.push_back(bigone);
                    bigone = vcTemp[i];
                }
                else
                {
                    oneRes.push_back(vcTemp[i]);
                }
            }
            vc.push_back(bigone);
        }
        vcRes.push_back(oneRes);
    }
    int iCurRank = 1;
    if(vc.size())
        vc[0]->iRank = iCurRank++;
    for(int i=vcRes.size()-1;i>=0;--i)
    {
        for(int j=0;j<vcRes[i].size();++j)
            vcRes[i][j]->iRank = iCurRank;
        iCurRank += vcRes[i].size();
    }
    sort(st,st+np,cmp);
    for(int i=0;i<np;++i)
        if(i) printf(" %d",st[i].iRank);
        else  printf("%d",st[i].iRank);
    return 0;
}
View Code

   1057题:分块搜索第k大的数字。

  

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
const char strPop[10] = "Pop";
const char strPush[10] = "Push";
const char strPeek[20] = "PeekMedian";
#define N (100010)
#define BLOCK  400
int block[400]={0};
int table[N]={0};
int FindK(int k)
{
    int cnt = 0;
    int i;
    for(i=0;i<400;++i)
    {
        if(cnt + block[i] >= k)
            break;
        cnt += block[i];
    }
    for(int j=i*BLOCK;j<N;++j)
    {
        cnt += table[j];
        if(cnt >= k)                //易错(之前是cnt==k),最后两个case就过不了了
            return j;

    }
    return 0;
}
int main()
{
    int n;
    scanf("%d",&n);
    vector<int> vc;
    for(int i=0;i<n;++i)
    {
        char cmd[20];
        scanf("%s",&cmd);
        if(strcmp(cmd,strPop)==0)
        {
            if(vc.size()==0)
            {
                printf("Invalid
");
            }
            else
            {
                int key = vc[vc.size()-1];
                printf("%d
",key);
                if(table[key]) --table[key];
                if(block[key/BLOCK]) --block[key/BLOCK];
                vc.pop_back();
            }
        }
        else if(strcmp(cmd,strPush)==0)
        {
            int num;
            scanf("%d",&num);
            vc.push_back(num);
            ++table[num];
            ++block[num/BLOCK];

        }
        else
        {
            if(vc.size()==0)
            {
                printf("Invalid
");
            }
            else
            {
                int k = vc.size();
                int iMid = k%2==0 ? k/2 : (k+1)/2;
                int iRes = FindK(iMid);
                printf("%d
",iRes);
            }
        }
    }
    return 0;
}
/*
17
Push 6
Push 6
Push 7
PeekMedian
*/
View Code

  1060题:题目还是挺难的,思路:

     1、删除输入数字之前的0,例如像00014这样的数组

          2、寻找小数点的位置dot,如果没有找到小数点,则位数等于字符串长度,如果找到了,位数等于dot。然后遍历字符串,如果发现前导0则去掉,位数减一,如果发现小数点,位数不变。这种算法需要考虑特殊情况0,如果发现是0,则位数强制赋值成0,不然位数时-1。

          3、在第二步计算位置的同时并且去掉前导0和小数点,然后对剩下的数字进行n为输出,不够补0,超过截取。

   4、0可以表示成 0.000*10^3,so。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
string getstr(string str,int m)
{
    int dot = str.find(".");
    int len = str.length();
    int wei = dot==-1?len:dot;
    string res = str;
    str = "";
    for(int i=0;i<len;++i)
    {
        if(res[i]=='0') --wei;
        else if(res[i]!='.')
        {
            res = res.substr(i,len-i);
            len = res.length();
            str = "";
            for(int j=0;j<len;++j)
                if(res[j]!='.') str+=res[j];
            break;
        }
    }

    len = str.length();
    if(len==0)  wei = 0;

    {
        res = "0.";
        int i;
        for(i=0;i<len&&i<m;++i)
            res += str[i];
        for(;i<m;++i)
            res += "0";
        char subfix[20];
        sprintf(subfix,"*10^%d",wei);
        res += subfix;
    }
    return res;
}
int main()
{
    #ifdef ONLINE_JUDGE
    #else
        freopen("test.txt","r",stdin);
    #endif
    int n;
    char str1[200],str2[200];
    scanf("%d%s%s",&n,str1,str2);
    string res1 = getstr(str1,n),res2=getstr(str2,n);
    if(strcmp(res1.c_str(),res2.c_str())==0)
        printf("YES %s
",res1.c_str());
    else    printf("NO %s %s
",res1.c_str(),res2.c_str());
    return 0;
}
View Code

 

    1061题:题目难懂,题目大致意思,第1个字符串和第2个字符串第一个共有字符表示哪一天(该字符要求A-F),第二个共同字符表示时间(0-9,A-N),第3个共同字符在第3和第4字符串中找(位置表示时间,0开始)

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
bool isEnglish(char c)
{
    if(c>='a'&&c<='z') return true;
    if(c>='A'&&c<='Z') return true;
    return false;
}
bool isBigEnglish(char c)
{
    if(c>='A'&&c<='Z') return true;
    return false;
}
bool isNum(char c)
{
    if(c>='0'&&c<='9') return true;
    return false;
}
int getPos(char c)
{
    if(c>='a'&&c<='z') return c-'a'+1;
    if(c>='A'&&c<='Z') return c-'A'+1;
    return 0;
}
int main()
{
    string weeks[] = {"","MON","TUE","WED","THU","FRI","SAT","SUN"};
    char s1[65],s2[65],s3[65],s4[65];
    scanf("%s%s%s%s",s1,s2,s3,s4);
    int week = 0,iWeek=0,h=0,m=0;
    int i;
    for(i=0;i<strlen(s1)&&i<strlen(s2);++i)
    {
        if(s1[i]==s2[i]&&isBigEnglish(s1[i])&&s1[i]<='G')
        {
            iWeek = i;
            week = getPos(s1[i]);
            week = (week-1)%7+1;
            break;
        }
    }

    for(i=i+1;i<strlen(s1)&&i<strlen(s2);++i)
    {
        if(s1[i]==s2[i]&&(isNum(s1[i])||(isBigEnglish(s1[i])&&s1[i]<='N')))
        {
            if(isNum(s1[i]))
            {
                h = s1[i]-'0';
            }
            else
            {
                h = s1[i]-'A'+10;
            }
            break;
        }
    }
    for(i=0;i<strlen(s3)&&i<strlen(s4);++i)
    {
        if(s3[i]==s4[i]&&isEnglish(s3[i]))
        {
            m = i;
            break;
        }
    }
    printf("%s %02d:%02d
",weeks[week].c_str(),h,m);
    return 0;
}
View Code

  1063题:正常情况会超时,所以不能把交集和并集全求出来,只能求出交集个数,然后通过减法得到并集个数。2种解法:

  1、通过set_intersection函数求:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
int main()
{
    int n,m;
    scanf("%d",&n);
    set<int> si[n];
    for(int i=0;i<n;++i)
    {
        scanf("%d",&m);
        for(int j=0;j<m;++j)
        {
            int temp;
            scanf("%d",&temp);
            si[i].insert(temp);
        }
    }
    int k;
    scanf("%d",&k);
    for(int i=0;i<k;++i)
    {
        int s,e;
        set<int> ss,st;
        scanf("%d%d",&s,&e);
        --s,--e;
        //交集
        set_intersection(si[s].begin(),si[s].end(),si[e].begin(),si[e].end(),
                         inserter(ss,ss.begin()));
        //并集
        /*set_union(si[s].begin(),si[s].end(),si[e].begin(),si[e].end(),
                         inserter(st,st.begin()));
        */
        int same = ss.size();
        int total = si[s].size()+si[e].size()-same;//st.size();
        if(total==0)   printf("0.0%%
");
        else printf("%.1lf%%
",100.0*same/total);

    }

    return 0;
}
View Code

       2、通过自己写求交集的函数,具体实现看代码

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
void getInsert(set<int> &in_set,const set<int> &s1,const set<int> &s2)
{
    set<int>::iterator it1 = s1.begin();
    set<int>::iterator it2 = s2.begin();
    while(it1!=s1.end()&&it2!=s2.end())
    {
        if(*it1==*it2)
        {
            in_set.insert(*it1);
            it1++;
            it2++;
        }
        else if(*it1 > *it2)     it2++;
        else      it1++;
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    set<int> s[n];
    for(int i=0;i<n;++i)
    {
        int m;
        scanf("%d",&m);
        for(int j=0;j<m;++j)
        {
            int a;
            scanf("%d",&a);
            s[i].insert(a);
        }
    }
    int k;
    scanf("%d",&k);
    for(int i=0;i<k;++i)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(a==b) printf("0.00%%
");
        else
        {
            --a;
            --b;
           set<int> si;
           getInsert(si,s[a],s[b]);
           double fRes = 100.0*si.size()/(s[a].size()+s[b].size()-si.size());
           printf("%.1lf%%
",fRes);
        }
    }
    return 0;
}
View Code

   1065题:用long long判断,通过判断溢出来判断大小,但是a+b的值需要用中间值保存,不然你只有可怜的12分。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;
int main()
{
    //freopen("test.txt","r",stdin);
    int T;
    scanf("%d",&T);
    for(int t=1;t<=T;++t)
    {
        long long int a,b,c;
        scanf("%lld%lld%lld",&a,&b,&c);
        bool bBig = true;
        /*
        错误,a+b需要赋值,具体为什么我也不知道
        if(a>0&&b>0&&a+b<=0) bBig = true;
        else if(a<0&&b<0&&a+b>=0) bBig = false;
        else bBig =a+b>c;
        */
        long long res = a+b;
        if(a>0&&b>0&&res<=0) bBig = true;
        else if(a<0&&b<0&&res>=0) bBig = false;
        else bBig =res>c;
        printf("Case #%d: %s
",t,bBig?"true":"false");

    }
    return 0;
}
View Code

  很神奇的是用long double也能过(注意不是double)

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;

int main()
{
    //freopen("test.txt","r",stdin);
    int T;
    scanf("%d",&T);
    for(int t=1;t<=T;++t)
    {
        long double a,b,c;
        scanf("%llf%llf%llf",&a,&b,&c);
        bool bBig = a+b>c;
        printf("Case #%d: %s
",t,bBig?"true":"false");
    }
    return 0;
}
View Code

   1067题:0所在的b,b所在位置是b2,把0放到b2的位置,把b放到b的位置。数组a,a[b]=i表示数字b在i位置。不用去管他最小交换个数,当0交换到0位置后,如果没有有序,则0先跟任意未排序好的数字交换位置,然后重复交换。用set保存未有序的数字。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;

int main()
{
    //freopen("test.txt","r",stdin);
    int n;
    scanf("%d",&n);
    int a[n],cnt=0;
    set<int> si;
    for(int i=0;i<n;++i)
    {
        int b;
        scanf("%d",&b);
        a[b] = i;
        if(b==i&&b) ++cnt;
        else if(b!=i&&b) si.insert(b);
    }
    int step=0;
    while(cnt < n-1)
    {
        if(a[0]==0)
        {
            int i = *(si.begin());
            if(a[i]!=i)
            {
                int b1 = a[i];  //i在b1位置
                a[0] = b1;  //0移到b1位置
                a[i] = 0;   //i移到0位置
            }

        }
        else
        {
            int b1 = a[0];  //0在b1位置
            int b2 = a[b1]; //b1在b2位置
            a[0] = b2;
            a[b1] = b1;
            si.erase(si.find(b1));
            ++cnt;
        }
        ++step;
    }
    printf("%d
",step);
    return 0;
}
View Code

  1068题:01背包,主要找路径时比较路径序号小的判断可能会搞错。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;

bool cmp(vector<int> v1,vector<int> v2)
{
   for(int i=0;i<v1.size()&&i<v2.size();++i)
   {
       if(v1[i] != v2[i])
            return v1[i] > v2[i];
   }
   return false;
}
int main()
{
    //freopen("test.txt","r",stdin);
    int n,m;
    scanf("%d%d",&n,&m);
    int dp[m+1];
    vector<int> path[m+1];
    for(int i=0;i<=m;++i)
       dp[i] = -1;
    int c[n];
    for(int i=0;i<n;++i)
        scanf("%d",&c[i]);
    dp[0] = 0;
    sort(c,c+n);
    for(int i=0;i<n;++i)
    {
        for(int v=m;v>=c[i];--v)
            if(dp[v-c[i]]>=0)
            {
                if(dp[v] < dp[v-c[i]]+c[i])
                {
                    dp[v] = dp[v-c[i]]+c[i];
                    path[v] = path[v-c[i]];
                    path[v].push_back(c[i]);
                }
                if(dp[v] == dp[v-c[i]]+c[i]&&cmp(path[v],path[v-c[i]]))
                {
                    dp[v] = dp[v-c[i]]+c[i];
                    path[v] = path[v-c[i]];
                    path[v].push_back(c[i]);
                }

            }
    }
    if(dp[m] != m)
    {
        printf("No Solution
");
    }
    else
    {
        for(int i=0;i<path[m].size();++i)
        {
            if(i) printf(" ");
            printf("%d",path[m][i]);
        }
    }
    return 0;
}
View Code

  1070题:不难,就是略坑,数量需要用double存储,用int一个case过不了。 

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
typedef struct mooncake
{
   double num;
   double fprice;
};
int cmp(const mooncake& m1,const mooncake& m2)
{
    if(m1.num == 0)
    {
        return 1;
    }
    else if(m2.num == 0)
    {
        return 0;
    }
    return 1.0*m1.fprice/m1.num > 1.0*m2.fprice/m2.num;
}
int main()
{
    int n,d;
    scanf("%d%d",&n,&d);
    mooncake mc[n];
    for(int i=0;i<n;++i)
        scanf("%lf",&mc[i].num);
    for(int i=0;i<n;++i)
        scanf("%lf",&mc[i].fprice);
    sort(mc,mc+n,cmp);
    double sum = 0;
    int i = 0;
    while(d>=0&&i<n)
    {
        if(mc[i].num==0||mc[i].fprice==0)
        {

        }
        else if(d >= mc[i].num)
        {
            d -= mc[i].num;
            sum += mc[i].fprice;
        }
        else
        {
            sum += (mc[i].fprice*(1.0*d/mc[i].num));
            d = 0;
        }
        ++i;
    }
    printf("%.2lf
",sum);
    return 0;
}
View Code

   

  1071题:恶心之处就在于不能在循环条件中使用strlen函数,否则超时

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
#define N (1048576+10)
bool isAlphanum(char c)
{
    if(c>='0'&&c<='9') return true;
    if(c>='a'&&c<='z') return true;
    if(c>='A'&&c<='Z') return true;
    return false;
}
char ToLower(char c)
{
    if(c>='A'&&c<='Z') c = 'a' + c-'A';
    return c;
}

int main()
{
    char str[N];
    fgets(str,sizeof(str),stdin);
    map<string,int> msi;
    int num = 0;
    string res = "";
    string word = "";
    int iStrLen = strlen(str);
    for(int i=0;i<iStrLen;++i)
    {
        char c = ToLower(str[i]);
        if(isAlphanum(c)==false) continue;
        word += c;
        if(isAlphanum(str[i+1])==false)
        {
            int tempcnt = ++msi[word];
            if((num==tempcnt&&word.length()<res.length())||num<tempcnt)
            {
                num = tempcnt;
                res = word;
            }
            word = "";
        }
    }
    if(res!="")
    {
        printf("%s %d
",res.c_str(),num);
    }
    return 0;
}
View Code

   

  1072题:题目不好理解,不难。1、求每个gas到house的最短距离,求最短距离中的最大。如果相等,求平均距离最小的。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<set>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;
#define N (1100)
int GetNo(char *str)
{
    int add = 0;
    if(str[0]=='G') ++str,add=1000;
    return add+atoi(str);
}
int n,m,k,ds;
int Map[N][N]={0};
int dp[N];
bool bVis[N];
void Dijkstra(int iStart)
{
    for(int i=1;i<N;++i)
        dp[i] = Map[iStart][i];
    for(int i=1;i<N;++i)
    {
        int iMindj = INT_MAX,iPos = iStart;
        for(int j=1;j<N;++j)
        {
            if(!bVis[j]&&iMindj>dp[j])
            {
                iMindj = dp[j];
                iPos = j;
            }
        }
        bVis[iPos] = true;
        if(dp[iPos] > ds) return;
        for(int j=1;j<N;++j)
        {
            //printf("dp[%d]=%d,dp[%d]=%d Map[%d][%d]=%d
",j,dp[j],iPos,dp[iPos],iPos,j,Map[iPos][j]);
            if(!bVis[j]&&Map[iPos][j]!=INT_MAX&&dp[j]>dp[iPos]+Map[iPos][j])
            {
                dp[j] = dp[iPos] + Map[iPos][j];
                //printf("res=%d
",dp[j]);
            }
        }
    }
}
int main()
{
    for(int i=0;i<N;++i)
        for(int j=0;j<N;++j)
            if(i==j)
                Map[i][j] = 0;
            else Map[i][j] = INT_MAX;
    scanf("%d%d%d%d",&n,&m,&k,&ds);
    for(int i=0;i<k;++i)
    {
        char str1[10],str2[10];
        int d;
        scanf("%s%s%d",str1,str2,&d);
        int a = GetNo(str1);
        int b = GetNo(str2);
        Map[a][b] = Map[b][a] = d;
    }
    int iMinSum = INT_MAX,iGas=-1,iMinPath=-1;
    for(int i=0;i<m;++i)
    {
        int gas = 1001+i;
        memset(bVis,0,sizeof(bVis));
        bVis[gas] = true;
        Dijkstra(gas);
        int j,Sum=0,iPath=INT_MAX;
        for(j=1;j<=n;++j)
        {
            //printf("gas=%d j=%d dp[j]=%d
",gas,j,dp[j]);
            if(dp[j]>ds) break;
            Sum += dp[j];
            if(iPath > dp[j]) iPath = dp[j];
        }
        if(j > n && (iMinPath < iPath||(iMinPath == iPath && iMinSum > Sum)))
        {
            iGas = gas;
            iMinSum = Sum;
            iMinPath = iPath;
        }
    }
    if(iGas==-1) printf("No Solution
");
    else
    {
        printf("G%d
",iGas-1000);
        printf("%.1lf %.1lf
",1.0*iMinPath,1.0*iMinSum/n);
    }
    return 0;
}
View Code

   1074题:稍微有点麻烦,dfs就可以了

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define N (100010)
struct ST
{
    int addr;
    int val;
    int nextaddr;
    ST()
    {
        nextaddr = -1;
    }
};
ST st[N];
bool bVis[N] = {true};
int iStart,n,k;
vector<int> res;
void travel(int iCurI,vector<int> vi)
{
    //printf("CurI=%05d
",iCurI);
    if(iCurI==-1 || bVis[iCurI])
    {
        if(vi.size()==k)
        for(int i=vi.size()-1;i>=0;--i)
        {
            res.push_back(vi[i]);
        }
        else
        {
             for(int i=0;i<vi.size();++i)
            {
                res.push_back(vi[i]);
            }
        }
        return;
    }
    else if(vi.size()==k)
    {
        for(int i=vi.size()-1;i>=0;--i)
        {
            res.push_back(vi[i]);
        }
        vi.clear();
    }
    bVis[iCurI] = true;
    vi.push_back(iCurI);
    int iNextI = st[iCurI].nextaddr;
    travel(iNextI,vi);
}
int main()
{
    scanf("%d%d%d",&iStart,&n,&k);
    for(int i=0;i<n;++i)
    {
        int iaddr,v,inext;
        scanf("%d%d%d",&iaddr,&v,&inext);
        st[iaddr].val = v;
        st[iaddr].nextaddr = inext;
        st[iaddr].addr = iaddr;
        bVis[iaddr] = false;
    }
    vector<int> tempvi;
    travel(iStart,tempvi);
    for(int i=0;i<res.size();++i)
    {
        int ID = res[i];
        if(i != res.size()-1)
        {
            int iNextID = res[i+1];
            printf("%05d %d %05d
",ID,st[ID].val,iNextID);
        }
        else
            printf("%05d %d -1
",ID,st[ID].val);
    }
    return 0;
}
View Code

  1075题:题目说明不清楚,坑点:当得分是-1时,表示编译未通过,在结果集中编译未通过的输出0,未提交的输出 -,当参赛者没有提交题目时,结果集中不输出此用户。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define K (6)
int prom[K]={100000000};
int n,k,m;
struct PAT
{
    int id;
    int grade[K];
    PAT()
    {
        for(int i=1;i<=k;++i)
            grade[i] = -2;
    }
    bool bUseful()
    {
        for(int i=1;i<=k;++i)
            if(grade[i]>=0) return true;
        return false;
    }
    int getSum() const
    {
        int sum = 0;
        for(int i=1;i<=k;++i)
            if(grade[i]>=0) sum+=grade[i];
        return sum;
    }
    int getPerfectNum() const
    {
        int res = 0;
        for(int i=1;i<=k;++i)
            if(grade[i]>=prom[i])
                ++res;
        return res;
    }
    void Print()
    {
        printf("%05d %d",id,getSum());
        for(int i=1;i<=k;++i)
            if(grade[i]==-1) printf(" 0");
            else if(grade[i]==-2) printf(" -");
            else printf(" %d",grade[i]);
        printf("
");
    }
};
int cmp(const PAT& p1,const PAT& p2)
{
    if(p1.getSum()!=p2.getSum()) return p1.getSum()>p2.getSum();
    if(p1.getPerfectNum()!=p2.getPerfectNum()) return p1.getPerfectNum() > p2.getPerfectNum();
    return p1.id < p2.id;
}
map<int,PAT> mip;
vector<PAT> vc;
int main()
{
    scanf("%d%d%d",&n,&k,&m);
    for(int i=1;i<=k;++i)
        scanf("%d",&prom[i]);
    for(int i=0;i<m;++i)
    {
        int ID,proID,sorce;
        scanf("%d%d%d",&ID,&proID,&sorce);
        if(ID <= n)
        {
            PAT &pat = mip[ID];
            pat.id = ID;
            if(pat.grade[proID] < sorce)
            {
                pat.grade[proID] = sorce;
            }
        }
    }
    map<int,PAT>::iterator it = mip.begin();
    for(;it!=mip.end();it++)
    {
        if(it->second.bUseful())
        {
            vc.push_back(it->second);
        }
    }
    sort(vc.begin(),vc.end(),cmp);
    PAT temp;
    vc.push_back(temp);     //加入一个哨兵,便于判断
    int iCurRank = 1;
    for(int i=0;i<vc.size()-1;++i)
    {
        printf("%d ",iCurRank);
        vc[i].Print();
        if(vc[i].getSum() != vc[i+1].getSum())
            iCurRank = i+2;
    }
    return 0;
}
View Code

   1077题:我以为是公有单词的后缀,没想到都不需要考虑是不是单词,想得多反而错误了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
int main()
{
    vector<string> vs;
    int n;
    scanf("%d",&n);
    getchar();
    for(int i=0;i<n;++i)
    {
        char str[300];
        fgets(str,sizeof(str),stdin);
        vs.push_back(str);
    }
    vector<char> res;
    bool bOK = true;
    for(int i=0;i<300 && bOK;++i)
    {
        char c;
        for(int j=0;j<vs.size();++j)
        {
            int len = vs[j].length();
            int iCurI = len - i -1;
            if(iCurI < 0)
            {
                bOK = false;
                break;
            }
            if(vs[j][iCurI]==' ')
            {
                //考虑了单词,其实空格也算公有的一部分
                //bOK = false;
                //break;
            }
            if(j==0) c = vs[j][iCurI];
            else if(vs[j][iCurI] != c)
            {
                bOK = false;
                break;
            }
        }
        if(bOK==true)
        {
            res.push_back(c);
        }
    }

    if(res.size()==1) printf("nai
");
    else
    {
        for(int i=res.size()-1;i>=0;--i)
            if(res[i]!='
') printf("%c",res[i]);
        printf("
");
    }
    return 0;
}
View Code

   1088题:用就可以了long long

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
struct Fen
{
    long long int a;
    long long int b;
};
long long gcd(long long a,long long b)
{
    if(a < 0) a = -a;
    if(b < 0) b = -b;
    if(b==0) return a;
    return gcd(b,a%b);
}
long long bei(long long a,long long b)
{
    if(a < 0) a = -a;
    if(b < 0) b = -b;
    return a/gcd(a,b)*b;
}
int main()
{
    int n;
    scanf("%d",&n);
    vector<Fen> vc;
    for(int i=0;i<n;++i)
    {
        Fen fen;
        scanf("%lld/%lld",&fen.a,&fen.b);
        if(fen.a&&fen.b) vc.push_back(fen);
    }

    long long com = 1;
    for(int i=0;i<vc.size();++i)
    {
        com = bei(com,vc[i].b);
    }

    long long son = 0;
    for(int i=0;i<vc.size();++i)
    {
        son += com/vc[i].b*vc[i].a;
    }
    if(son == 0) printf("0
");
    else
    {
        long long temp = gcd(son,com);
        son = son/temp;
        com = com/temp;
        bool bN = false;
        if(son > 0 && com <0 || son<0 && com>0)
        {
            bN = true;
            if(son<0) son = -son;
            if(com<0) com = -com;
        }
        if(son/com>0)
        {
            if(bN) printf("-");
            printf("%lld",son/com);
            son = son%com;
            if(son) printf(" ");
        }
        else if(bN) printf("-");
        if(son)
        {
            printf("%lld/%lld",son,com);
        }
        printf("
");
    }
    return 0;
}
View Code

   1082题 108 yi Bai ling ba  1008 yi Qian ling ba

  

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
const int YI = 100000000;
const int WAN = 10000;
string strNum[] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
void Print(long long int n)
{
    if(n>=1000)
    {
        printf("%s Qian",strNum[n/1000].c_str());
        n = n%1000;
        if(n)
        {
            printf(" ");
            if(n<100) printf("ling ");
        }
    }
    if(n>=100)
    {
        printf("%s Bai",strNum[n/100].c_str());
        n=n%100;
        if(n)
        {
            printf(" ");
            if(n<10) printf("ling ");
        }
    }
    if(n>=10)
    {
        printf("%s Shi",strNum[n/10].c_str());
        n = n%10;
        if(n) printf(" ");
    }
    if(n) printf("%s",strNum[n].c_str());
}
int main()
{
    long long int n;
    scanf("%lld",&n);
    if(n==0) printf("ling
");
    else
    {
        if(n<0)
        {
            printf("Fu ");
            n = -n;
        }
        if(n>=YI)
        {
            printf("%s Yi",strNum[n/YI].c_str());
            n = n%YI;
            if(n)
                if(n<10000000) printf(" ling ");
                else printf(" ");
        }
        if(n>=WAN)
        {
            Print(n/WAN);
            printf(" Wan");
            n = n%WAN;
            if(n)
                if(n<1000) printf(" ling ");
                else printf(" ");
        }
        if(n) Print(n);
        printf("
");
    }
    return 0;
}
View Code

  1084题:123 12这个容易错

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
char toBig(char c)
{
    if('a'<=c&&c<='z') return c-'a'+'A';
    return c;
}
int main()
{
    char str1[100],str2[100];
    scanf("%s%s",str1,str2);
    int i=0,j=0;
    int len1=strlen(str1),len2=strlen(str2);
    string res="";
    set<char> sc;
    for(;i<len1;)
    {
        char c1 = toBig(str1[i]);
        char c2 = '@';
        if(j<len2)
        {
            c2 = toBig(str2[j]);
        }
        if(c1==c2) ++i,++j;
        else
        {
            if(sc.find(c1)==sc.end())
            {
                sc.insert(c1);
                res += c1;
            }
            ++i;
        }
    }
    printf("%s
",res.c_str());
    return 0;
}
View Code

   1087题:容易超时

dfs的解法:

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;
#define N (26*26*26+10)
int toNum(char* str)
{
    return (str[0]-'A')*26*26+(str[1]-'A')*26+(str[2]-'A');
}
int hap[N] = {0};
int Map[N][N];
bool bVis[N] = {false};
int n,k;
char strStart[4];
vector<int> vc[N];
string toStr(int n)
{
    char str[4]={''};
    str[0] = n/26/26+'A';
    str[1] = n/26%26 + 'A';
    str[2] = n%26 + 'A';
    return str;
}
int iMaxHap = 0;
int iMinCost = INT_MAX;
int paths = 0;
int dst = toNum("ROM");
vector<int> vcRes;
void dfs(int iCurI,int iCost,int h,vector<int> v)
{
    //printf("%s cost=%d iMincost=%d h=%d iMaxHap=%d
",toStr(iCurI).c_str(),iCost,iMinCost,h,iMaxHap);
    if(iCost == iMinCost && iCurI==dst)
    {
        ++paths;
    }
    else if(iCost < iMinCost && iCurI == dst)
    {
        paths = 1;
    }
    if(iCost > iMinCost ||
       (iCost==iMinCost&&h<iMaxHap) ||
       (iCost==iMinCost&&h==iMaxHap&&v.size()>vcRes.size())||
       (iCost==iMinCost&&h==iMaxHap&&v.size()==vcRes.size())/*这一行不加容易超时*/) return;
    if(iCurI==dst)
    {
        //printf("minCost=%d maxHap=%d
",iMinCost,iMaxHap);
        vcRes = v;
        iMinCost = iCost;
        iMaxHap = h;
        return;
    }
    bVis[iCurI] = true;
    for(int i=0;i<vc[iCurI].size();++i)
    {
        int iNextI = vc[iCurI][i];
        if(!bVis[iNextI])
        {
            v.push_back(iNextI);
            dfs(iNextI,iCost+Map[iCurI][iNextI],h+hap[iNextI],v);
            v.pop_back();
        }
    }
    bVis[iCurI] = false;
}
int main()
{
    scanf("%d%d%s",&n,&k,strStart);
    for(int i=0;i<n-1;++i)
    {
        char str[4];
        int h;
        scanf("%s%d",str,&h);
        int iStr = toNum(str);
        hap[iStr] = h;
    }
    for(int i=0;i<k;++i)
    {
        char str1[4],str2[4];
        int a,b,len;
        scanf("%s%s%d",str1,str2,&len);
        a = toNum(str1);
        b = toNum(str2);
        //if(Map[a][b]==0)
        {
            vc[a].push_back(b);
            vc[b].push_back(a);
        }
        Map[a][b] = Map[b][a] = len;
    }
    vector<int> temp;
    temp.push_back(toNum(strStart));
    dfs(toNum(strStart),0,0,temp);
    if(vcRes.size()>1)
    {
        printf("%d %d %d %d
",paths,iMinCost,iMaxHap,iMaxHap/(vcRes.size()-1));
    }
    for(int i=0;i<vcRes.size();++i)
    {
        if(i) printf("->");
        printf("%s",toStr(vcRes[i]).c_str());
    }
    printf("
");
    return 0;
}
View Code

 dijkstra方法:不容易理解,而且容易出错,但是效率高,自己把地名转换成数字。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<climits>
#include<algorithm>
using namespace std;
#define N (210)
map<int,string> mis;
map<string,int> msi;
int n;
int H[N]={0};
bool bVis[N]={0};
int Map[N][N];
struct ST
{
    int cost;
    int hap;
    int pre;
    int cnt;
    int iStep;
    ST()
    {
        hap = 0;
        pre = 0;
        cnt = 1;
        iStep = 1;
    }
};
ST dp[N];
void dijstra()
{
    for(int i=0;i<n;++i)
    {
        dp[i].cost = Map[0][i];
        dp[i].hap = H[i];
    }

    for(int i=1;i<n;++i)
    {
        int minDj = INT_MAX,pos = 0;
        for(int j=1;j<n;++j)
        {
            if(!bVis[j]&&dp[j].cost < minDj)
            {
                minDj = dp[j].cost;
                pos = j;
            }
        }
        bVis[pos] = true;
        for(int j=1;j<n;++j)
        {
            if(!bVis[j]&&Map[pos][j]!=INT_MAX)
            {
                if(dp[j].cost > dp[pos].cost + Map[pos][j])
                {
                    dp[j].cost = dp[pos].cost + Map[pos][j];
                    dp[j].pre = pos;
                    dp[j].hap = dp[pos].hap + H[j];
                    dp[j].cnt = dp[pos].cnt;
                    dp[j].iStep = dp[pos].iStep+1;
                }
                else if(dp[j].cost == dp[pos].cost + Map[pos][j])
                {
                    dp[j].cnt += dp[pos].cnt;
                    if(dp[j].hap < dp[pos].hap+H[j])
                    {
                        dp[j].hap = dp[pos].hap+H[j];
                        dp[j].pre = pos;
                        dp[j].iStep = dp[pos].iStep+1;
                    }
                    else if(dp[j].hap == dp[pos].hap+H[j] && dp[j].iStep > dp[pos].iStep+1)
                    {
                        dp[j].pre = pos;
                        dp[j].iStep = dp[pos].iStep+1;
                    }
                }
            }
        }
    }
}
int main()
{
    int k;
    char strStart[4];
    scanf("%d%d%s",&n,&k,strStart);
    msi[strStart] = 0;
    mis[0] = strStart;
    for(int i=1;i<n;++i)
    {
        char str[4];
        scanf("%s%d",str,&H[i]);
        msi[str] = i;
        mis[i] = str;
    }
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)
            if(i==j) Map[i][j] = 0;
            else Map[i][j] = INT_MAX;
    for(int i=0;i<k;++i)
    {
        char s1[4],s2[4];
        int cost;
        scanf("%s%s%d",s1,s2,&cost);
        int a1 = msi[s1],a2=msi[s2];
        Map[a1][a2] = Map[a2][a1] = cost;
    }
    int dst = msi["ROM"];
    dijstra();
    printf("%d %d %d %d
",dp[dst].cnt,dp[dst].cost,dp[dst].hap,dp[dst].hap/dp[dst].iStep);
    vector<int> res;
    for(int i=dst;i!=0;i=dp[i].pre)
    {

        res.push_back(i);
    }
    res.push_back(0);
    bool bFirst = true;
    for(int i=res.size()-1;i>=0;--i)
    {
        if(bFirst) bFirst = false;
        else printf("->");
        printf("%s",mis[res[i]].c_str());
    }
    printf("
");
    return 0;
}
View Code

      1088题:输入也要简化,只顾输出化简了,所以会有一个case过不了

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<climits>
#include<iterator>
using namespace std;
long long gcd(long long a,long long b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}
string getstr(long long a)
{
    char str[100];
    sprintf(str,"%lld",a);
    return str;
}
struct Fen
{
    long long a;
    long long b;
    void change()
    {
        if(b==0) return;
        if(b<0) a = -a,b=-b;
        long long g = gcd(abs(a),b);
        a = a/g;
        b = b/g;
    }
    string gettext()
    {
        change();
        if(b==0)
        {
            return "Inf";
        }
        else if(a==0)
        {
            return "0";
        }
        long long ia = abs(a),ib = b;
        string res = "";
        if(a<0) res="(-";
        if(ib==1) res += getstr(ia);
        else
        {
            long long k = ia/ib;
            ia = ia%ib;
            if(k>0) res = res + getstr(k) + " ";
            res = res + getstr(ia) + "/" + getstr(ib);

        }
        if(a<0) res+=")";
        return res;
    }
};
Fen add(Fen f1,Fen f2)
{
    Fen f;
    f.a = f1.a*f2.b + f2.a*f1.b;
    f.b = f1.b*f2.b;
    return f;
}
Fen jian(Fen f1,Fen f2)
{
    Fen f;
    f.a = f1.a*f2.b - f2.a*f1.b;
    f.b = f1.b*f2.b;
    return f;
}
Fen cheng(Fen f1,Fen f2)
{
    Fen f;
    f.a = f1.a*f2.a;
    f.b = f1.b*f2.b;
    return f;
}
Fen chu(Fen f1,Fen f2)
{
    Fen f;
    f.a = f1.a*f2.b;
    f.b = f1.b*f2.a;
    return f;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("1.txt","r",stdin);
    #endif // ONLINE_JUDGE
    Fen f1,f2;
    scanf("%lld/%lld",&f1.a,&f1.b);
    scanf("%lld/%lld",&f2.a,&f2.b);
    Fen f;
    f = add(f1,f2);
    printf("%s + %s = %s
",f1.gettext().c_str(),f2.gettext().c_str(),f.gettext().c_str());
    f = jian(f1,f2);
    printf("%s - %s = %s
",f1.gettext().c_str(),f2.gettext().c_str(),f.gettext().c_str());
    f = cheng(f1,f2);
    printf("%s * %s = %s
",f1.gettext().c_str(),f2.gettext().c_str(),f.gettext().c_str());
    f = chu(f1,f2);
    printf("%s / %s = %s
",f1.gettext().c_str(),f2.gettext().c_str(),f.gettext().c_str());

    return 0;
}
View Code

      1089题:case2是插入排序,。。。分治排序跟正常的2分分治不一样。使用最暴力的解法就行了。case是这样的比如2 1 3 4 5 9 8。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<climits>
#include<iterator>
using namespace std;
bool equalarr(int* a,int* b,int n)
{
    for(int i=0;i<n;++i)
        if(a[i]!=b[i]) return false;
    return true;
}
/*
1 2 3 4 9 7
1 2 3 4 9 7
*/
bool isInsert(int* a,int* b,int n)
{
    int temp[n];
    memcpy(temp,a,sizeof(temp));
    for(int i=2;i<=n;++i)
    {
        bool bEqu = equalarr(temp,b,n);
        sort(temp,temp+i);
        //比如1 2 3 4 9 7,你排到i=2的时候就相等了,但是我们期望的是i=5的时候。
        if(bEqu&&!equalarr(temp,b,n))
        {
            printf("Insertion Sort
");
            for(int j=0;j<n;++j)
            {
                if(j) printf(" ");
                printf("%d",temp[j]);
            }
            return true;
        }
    }
    printf("Merge Sort
");
    return false;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("1.txt","r",stdin);
    #endif // ONLINE_JUDGE
    int n;
    scanf("%d",&n);
    int a[n],b[n];
    for(int i=0;i<n;++i)
        scanf("%d",&a[i]);
    for(int i=0;i<n;++i)
        scanf("%d",&b[i]);
    bool bInsert = isInsert(a,b,n);
    if(!bInsert)
    {
        for(int len=2;;len*=2)
        {
            bool bequ = equalarr(a,b,n);
            for(int i=0;i<n;i+=len)
            {
                sort(a+i,a+min((i+len),n));
            }
            if(bequ)
            {
                for(int i=0;i<n;++i)
                {
                    if(i) printf(" ");
                    printf("%d",a[i]);
                }
                printf("
");
                break;
            }
        }
    }
    return 0;
}
View Code

    1091题:用dfs会导致最后两个是段错误,因为dfs在图很大的时候回爆栈(递归太多)。数组如果是a[65][1300][130]会超时,a[1300][130][65]就会正常,注意了。使用非递归的bfs。其实我觉得像拓扑排序。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int m,n,l,t;
int a[1300][130][65];
struct Point
{
    int l;
    int m;
    int n;
    Point(int l,int m,int n)
    {
        this->l = l;
        this->m = m;
        this->n = n;
    }
};
bool bOK(int curl,int curm,int curn)
{
    if(curl<0||curl>=l||curm<0||curm>=m||curn<0||curn>=n) return false;
    if(a[curm][curn][curl]==0) return false;
    return true;
}
int bfs(int curl,int curm,int curn)
{
    int cnt = 0;
    Point p(curl,curm,curn);
    if(bOK(p.l,p.m,p.n)==false) return 0;
    a[curm][curn][curl]=0;
    queue<Point> qi;
    qi.push(p);
    while(!qi.empty())
    {
        p = qi.front();
        qi.pop();
        ++cnt;
        if(bOK(p.l+1,p.m,p.n))
        {
            qi.push(Point(p.l+1,p.m,p.n));
            a[p.m][p.n][p.l+1] = 0;
        }
        if(bOK(p.l-1,p.m,p.n))
        {
            qi.push(Point(p.l-1,p.m,p.n));
            a[p.m][p.n][p.l-1] = 0;
        }
        if(bOK(p.l,p.m+1,p.n))
        {
            qi.push(Point(p.l,p.m+1,p.n));
            a[p.m+1][p.n][p.l] = 0;
        }
        if(bOK(p.l,p.m-1,p.n))
        {
            qi.push(Point(p.l,p.m-1,p.n));
            a[p.m-1][p.n][p.l] = 0;
        }
        if(bOK(p.l,p.m,p.n+1))
        {
            qi.push(Point(p.l,p.m,p.n+1));
            a[p.m][p.n+1][p.l] = 0;
        }
        if(bOK(p.l,p.m,p.n-1))
        {
            qi.push(Point(p.l,p.m,p.n-1));
            a[p.m][p.n-1][p.l] = 0;
        }

    }
    return cnt>=t?cnt:0;
}
int main()
{
    #ifdef ONLINE_JUDGE
    #else
        freopen("test.txt","r",stdin);
    #endif // ONLINE_JUDGE
    scanf("%d%d%d%d",&m,&n,&l,&t);
    for(int i=0;i<l;++i)
        for(int j=0;j<m;++j)
            for(int k=0;k<n;++k)
                scanf("%d",&a[j][k][i]);
    int res=0;
    for(int i=0;i<l;++i)
        for(int j=0;j<m;++j)
            for(int k=0;k<n;++k)
            {
                res += bfs(i,j,k);
            }
    printf("%d
",res);
    return 0;
}
View Code

   1095题:模拟题,需要注意1:排序后,最接近的in和out一组,例如 in1,in2,out1,out2,in2和out1之间是这车在校园中逗留的时间,in1和out2是不符合规则的数据需要丢弃;2逗留时间是out2-out1,但是out2是不计入在学校的个数的。

  以下是是用hash的思想做的,用两个hash数组记录当前时间车子的数量,Ti[24*60*60]当前秒车子停的个数,Tm[24*60]当前分钟车子的个数,因为光用ti一个会超时,所以我想如果in和out之间过大时,比如7:10:10到7:30:20出来,我不就可以这样算,7:10:10到7:10:59,每次遍历1秒,每次Ti加1;7:11:00到7:30:59每次遍历1分钟,每次Tm加1。最后7:30:00到7:30:19(最后一秒不算),每次遍历1秒,Ti加1。所以h:m:s时车子的个数是:res = 60*60*h+60*m+s,个数=Ti[res]+Tm[res/60]

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
#define N (10010)
#define TN (24*60*60)
struct CarInOutTime
{
    int tick;
    bool bIn;
    CarInOutTime(int h,int m,int s,char* opt)
    {
        if(strcmp(opt,"in")==0) bIn = true;
        else bIn = false;
        tick = 60*60*h+60*m+s;
    }
};
int cmp(const CarInOutTime& t1,const CarInOutTime& t2)
{
    return t1.tick<t2.tick;
}
int Ti[TN];         //每秒钟车的个数
int Tm[TN/60];      //每分钟
struct Car
{
    string carid;//车牌
    vector<CarInOutTime> inouttime;   //出入时间
    int captime;                   //在校园中逗留的时间
    Car(){captime=0;}
    void Add(char* id,int h,int m,int s,char* opt)
    {
        carid = id;
        inouttime.push_back(CarInOutTime(h,m,s,opt));
    }
    void Deal()
    {
        sort(inouttime.begin(),inouttime.end(),cmp);    //排序
        int  intick;    //进入的人时间戳
        bool bhavein=false;       //前面是否进入过
        for(int i=0;i<inouttime.size();++i)
        {
            if(inouttime[i].bIn)
            {
                bhavein = true;
                intick = inouttime[i].tick;
            }
            else if(bhavein&&!inouttime[i].bIn)
            {
                bhavein = false;
                captime += inouttime[i].tick-intick;
                for(int tick=intick;tick<inouttime[i].tick;)
                {
                    if(tick%60==0&&tick+60<=inouttime[i].tick)
                    {
                        ++Tm[tick/60];   //因为这车在这一分钟都在
                        tick += 60;
                    }
                    else  ++Ti[tick++];
                }
            }
        }
        inouttime.clear();//清空
    }
};
map<string,int> msi;    //把车的id转换成编号(从0开始)
Car cars[N];
int main()
{
    #ifdef ONLINE_JUDGE
    #else
        freopen("test.txt","r",stdin);
    #endif // ONLINE_JUDGE
    int n,k;
    scanf("%d%d",&n,&k);
    int carcnt = 0;
    for(int i=0;i<n;++i)
    {
        char carid[10],opt[5];
        int h,m,s;
        scanf("%s %d:%d:%d %s",carid,&h,&m,&s,opt);
        if(msi.find(carid)==msi.end())
            msi[carid] = carcnt++;
        cars[msi[carid]].Add(carid,h,m,s,opt);
    }
    vector<string> vs;//记录逗留最长时间的车牌号
    int maxti = 0;
    for(int i=0;i<carcnt;++i)
    {
        cars[i].Deal();
        if(cars[i].captime >= maxti)
        {
            if(cars[i].captime > maxti) vs.clear(),maxti = cars[i].captime;
            vs.push_back(cars[i].carid);
        }
    }
    for(int i=0;i<k;++i)
    {
        int h,m,s;
        scanf("%d:%d:%d",&h,&m,&s);
        int tick = h*60*60+m*60+s;
        printf("%d
",Ti[tick]+Tm[tick/60]);
    }
    sort(vs.begin(),vs.end());
    for(int i=0;i<vs.size();++i)
        printf("%s ",vs[i].c_str());
    printf("%02d:%02d:%02d
",maxti/3600,maxti%3600/60,maxti%60);
    return 0;
}
View Code

  1096题:容易超时,已知最大的长度是12,你可以从2*3...*13,所以从len等于12开始累乘,发现积能被n整除则输出,当len=1的时候需要判断sum*sum是否大于n,否则会超时,b当sum*sum大于n时,说明该数时素数则必须另外输出。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
using namespace std;
long long int getSum(int n,int len)
{
    long long int sum = 1;
    for(int i=0;i<len;++i)
        sum = sum*(n+i);
    return sum;
}
int main()
{
  int n;
  scanf("%d", &n);

  for(int len=12;len>=1;--len)
  {
      long long int sum;
      for(int i=2;(sum=getSum(i,len))<=n;++i)
      {
          //sum必须是long long否则撑起来会负数。
          if(len==1&&sum*sum > n)
          {
              break;
          }
          if(n%sum==0)
          {
              printf("%d
",len);
              for(int j=0;j<len;++j)
              {
                  if(j) printf("*");
                  printf("%d",i+j);
              }
              return 0;
          }
      }
  }
  printf("1
%d
",n);
  return 0;
}
View Code

  1103题:dfs需要剪枝不然会超时,其实有点像N皇后的题目

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
int mypow(int n,int p)
{
    int res = 1;
    for(int i=0;i<p;++i)
    {
        res *= n;
    }
    return res;
}
int n,k,p,sum2=0;
bool bOK;
vector<int> res;
void dfs(int sum,int totalsum,int i,int len,vector<int> vi)
{
    //printf("totalsum=%d i=%d
",totalsum,i);
    if(len==k)
    {
        if(sum==n)
        {
            if(sum2 < totalsum)
            {
                sum2 = totalsum;
                bOK = true;
                res = vi;
            }
        }
        return;
    }
    if(sum >= n)
    {
        return;
    }
    /*容易超时,过滤*/
    if(totalsum + (k-len)*i < sum2)
    {
        return;
    }
   
    for(int j = i;j>=1;--j)
    {
        vi.push_back(j);
        dfs(sum+mypow(j,p),totalsum+j,j,len+1,vi);
        vi.pop_back();
    }
}
int main()
{
    //freopen("test.txt","r",stdin);
    scanf("%d%d%d",&n,&k,&p);
    if(k==1)
    {
        int sum;
        for(int i=1;(sum=mypow(i,p))<=n;++i)
        {
            if(sum == n)
            {
                printf("%d = ",n);
                printf("%d^%d
",i,p);
                return 0;
            }
        }
        printf("Impossible
");
    }
    else
    {
        int sum,iMaxF = 0;
        for(int i=1;true;++i)
        {
            sum = mypow(i,p)+(k-1);
            if(sum >= n)
            {
                iMaxF = i;
                break;
            }
        }
        for(int i=iMaxF;i>=1;--i)
        {
            vector<int> vi;
            vi.push_back(i);
            dfs(mypow(i,p),i,i,1,vi);
        }
        if(bOK)
        {
            printf("%d = ",n);
            for(int i=0;i<res.size();++i)
            {
                if(i) printf(" + ");
                printf("%d^%d",res[i],p);
            }
            printf("
");
        }
        else
            printf("Impossible
");
    }
    return 0;
}
View Code

   1107题:并查集

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
#define H (1100)
int p[H];
int peo[H];     //记录每个人的第一个爱好
int Find(int x)
{
    if(p[x]==x) return x;
    int root = Find(p[x]);
    p[x] = root;
    return root;
}
void Union(int x,int y)
{
    int a = Find(x);
    int b = Find(y);
    if(a!=b)
    {
        p[a] = b;
    }
}
int main()
{
    //freopen("test.txt","r",stdin);
    for(int i=0;i<H;++i)
        p[i] = i;
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;++i)
    {
        int k,pre;
        scanf("%d:",&k);
        for(int ik=0;ik<k;++ik)
        {
            int a;
            scanf("%d",&a);
            if(ik==0)
            {
                peo[i] = a;
            }
            else
            {
                Union(pre,a);
            }
            pre = a;
        }
    }
    map<int,int> mii;
    for(int i=0;i<n;++i)
        ++mii[Find(peo[i])];
    vector<int> vi;
    map<int,int>::iterator it = mii.begin();
    for(;it!=mii.end();it++)
        vi.push_back(it->second);
    sort(vi.begin(),vi.end());
    printf("%d
",vi.size());
    for(int i=vi.size()-1;i>=0;--i)
    {
        if(i) printf("%d ",vi[i]);
        else printf("%d
",vi[i]);
    }
    return 0;
}
View Code

  1109题:k行看成k列,然后总是错误

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
struct ST
{
    char name[10];
    int height;
};
int cmp(const ST &s1,const ST &s2)
{
    if(s1.height != s2.height) return s1.height > s2.height;
    return strcmp(s1.name,s2.name)<0;
}
void Print(ST* st,int istart,int len)
{
    string strname[len];
    int imid = (len)/2;
    strname[imid] = st[istart].name;
    for(int i=istart+1,j=1;i<istart+len;i += 2,++j)
    {
        if(i<istart+len)
            strname[imid-j] = st[i].name;
        if(i+1<istart+len)
            strname[imid+j] = st[i+1].name;
    }
    for(int i=0;i<len;++i)
    {
        if(i) printf(" ");
        printf("%s",strname[i].c_str());
    }
    printf("
");
}
int main()
{
    //freopen("test.txt","r",stdin);
    int n,k;
    scanf("%d%d",&n,&k);
    ST st[n];
    for(int i=0;i<n;++i)
    {
        scanf("%s%d",st[i].name,&st[i].height);
    }
    sort(st,st+n,cmp);
    k = n/k;
    for(int i=0;i<n;)
    {
        int len = k;
        if(i==0)
        {
            len = (n>=k?k:0)+n%k;
        }
        Print(st,i,len);
        i += len;
    }
    return 0;
}
View Code

  1110题:进行bfs遍历,每次遍历完需要判断该层是否是2的(level-1)次方,如果有下一层,而且该层不满足2的level-1次方,说明不是bst(之前没考虑所以错了)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define N (100)
struct Node
{
    int key;
    Node *left;
    Node *right;
    Node(){left = right = NULL;}
};
Node nodes[N];
int  indegree[N]={0};
int cnt = 0;
Node* lastnode = NULL;
bool bVis[N] = {0};
void level_travel(vector<Node*> vn,int level)
{
    if(vn.size()==0) return;
    cnt += vn.size();
    vector<Node*> vnnext;
    for(int i=0;i<vn.size();++i)
    {
        Node* node = vn[i];
        if(node->left==NULL)
        {
           break;
        }
        if(bVis[node->left->key]) return;
        bVis[node->left->key] = true;
        vnnext.push_back(node->left);
        lastnode = node->left;
        if(node->right==NULL)
        {
            break;
        }
        if(bVis[node->right->key]) return;
        bVis[node->right->key] = true;
        vnnext.push_back(node->right);
        lastnode = node->right;
    }

    if(vnnext.size())
    {
        int stdcnt = 1;
        for(int i=1;i<level;++i)
        {
            stdcnt *= 2;
        }
        if(stdcnt != vn.size())
        {
            return;
        }
        level_travel(vnnext,level+1);
    }
}
int main()
{
    //freopen("test.txt","r",stdin);
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;++i)
    {
        char cl[5],cr[5];
        scanf("%s%s",cl,cr);
        nodes[i].key = i;
        if(cl[0]!='-')
        {
            nodes[i].left = &nodes[atoi(cl)];
            ++indegree[atoi(cl)];
        }
        if(cr[0]!='-')
        {
            nodes[i].right = &nodes[atoi(cr)];
            ++indegree[atoi(cr)];
        }
    }
    Node* root = NULL;
    for(int i=0;i<n;++i)
    {
        if(indegree[i]==0)
        {
            root = &nodes[i];
            break;
        }
    }
    vector<Node*> vn;
    lastnode = root;
    bVis[root->key] = true;
    vn.push_back(root);
    level_travel(vn,1);
    if(cnt == n)
    {
        printf("YES %d
",lastnode->key);
    }
    else
    {
        printf("NO %d
",root->key);
    }
    return 0;
}
View Code

  1111题:dfs会超时,最多只能27分。只能用dijkstra,并且使用pre数组记录路径。写了40分钟泪崩。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define N (510)
#define INF (1<<30)
int Dis[N][N];
int Tim[N][N];
bool bVis[N];
int startpos,endpos;
int n,m;
int resDis;
vector<int> vcDis;
int resTim;
vector<int> vcTim;
void dijkstraDis()
{
    memset(bVis,0,sizeof(bVis));
    int dp[n];
    int fast[n];
    int pre[n];
    for(int i=0;i<n;++i)
    {
        dp[i] = Dis[startpos][i];
        fast[i] = Tim[startpos][i];
        pre[i] = startpos;
    }
    bVis[startpos] = true;
    for(int i=0;i<n;++i)
    {
        int mindj=INF,minti=INF,pos = startpos;
        for(int j=0;j<n;++j)
        {
            if(!bVis[j]&&(dp[j]<mindj||
                          dp[j]==mindj&&fast[j]<minti))
            {
                mindj = dp[j];
                minti = fast[j];
                pos = j;
            }
        }
        bVis[pos] = true;
        for(int j=0;j<n;++j)
        {
            if(!bVis[j] && (dp[j] > dp[pos]+Dis[pos][j] ||
                                dp[j] == dp[pos]+Dis[pos][j]&&fast[j] > fast[pos]+Tim[pos][j]))
            {
                pre[j] = pos;
                dp[j] = dp[pos]+Dis[pos][j];
                fast[j] = fast[pos]+Tim[pos][j];
            }
        }
        if(bVis[endpos])
        {
            resDis = dp[endpos];
            for(int j=endpos;true;j=pre[j])
            {
                vcDis.push_back(j);
                if(j==startpos)
                {
                    break;
                }
            }
            reverse(vcDis.begin(),vcDis.end());
            return;
        }
    }
}
void dijkstraTim()
{
    memset(bVis,0,sizeof(bVis));
    int dp[n];
    int ins[n];
    int pre[n];
    for(int i=0;i<n;++i)
    {
        dp[i] = Tim[startpos][i];
        ins[i] = 0;
        pre[i] = startpos;
    }
    bVis[startpos] = true;
    for(int i=0;i<n;++i)
    {
        int mindj=INF,minins=INF,pos = startpos;
        for(int j=0;j<n;++j)
        {
            if(!bVis[j]&&(dp[j]<mindj||
                          dp[j]==mindj&&ins[j]<minins))
            {
                mindj = dp[j];
                minins = ins[j];
                pos = j;
            }
        }
        bVis[pos] = true;
        for(int j=0;j<n;++j)
        {
            if(!bVis[j] && (dp[j] > dp[pos]+Tim[pos][j] ||
                                dp[j] == dp[pos]+Tim[pos][j]&&ins[j] > ins[pos]+1))
            {
                pre[j] = pos;
                dp[j] = dp[pos]+Tim[pos][j];
                ins[j] = ins[pos]+1;
            }
        }
        if(bVis[endpos])
        {
            resTim = dp[endpos];
            for(int j=endpos;true;j=pre[j])
            {
                vcTim.push_back(j);
                if(j==startpos)
                {
                    break;
                }
            }
            reverse(vcTim.begin(),vcTim.end());
            return;
        }
    }
}
bool isVecSame(vector<int> v1,vector<int> v2)
{
    if(v1.size()!= v2.size()) return false;
    for(int i=0;i<v1.size();++i)
    {
        if(v1[i] != v2[i]) return false;
    }
    return true;
}
int main()
{
    //freopen("test.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)
        {
            if(i==j)
            {
                Dis[i][j] = Tim[i][j] = 0;
            }
            else
            {
                Dis[i][j] = Tim[i][j] = INF;
            }
        }
    for(int i=0;i<m;++i)
    {
        int v1,v2,oneway,len,tim;
        scanf("%d%d%d%d%d",&v1,&v2,&oneway,&len,&tim);
        Dis[v1][v2] = len;
        Tim[v1][v2] = tim;
        if(oneway==0)
        {
            Dis[v2][v1] = len;
            Tim[v2][v1] = tim;
        }
    }
    scanf("%d%d",&startpos,&endpos);
    dijkstraDis();
    dijkstraTim();
    if(isVecSame(vcDis,vcTim))
    {
        printf("Distance = %d; Time = %d: ",resDis,resTim);
        for(int i=0;i<vcDis.size();++i)
        {
            if(i) printf(" -> ");
            printf("%d",vcDis[i]);
        }
        printf("
");
    }
    else
    {
        printf("Distance = %d: ",resDis);
        for(int i=0;i<vcDis.size();++i)
        {
            if(i) printf(" -> ");
            printf("%d",vcDis[i]);
        }
        printf("
");
        printf("Time = %d: ",resTim);
        for(int i=0;i<vcTim.size();++i)
        {
            if(i) printf(" -> ");
            printf("%d",vcTim[i]);
        }
        printf("
");
    }
    return 0;
}
View Code

  1117题:题意有点坑,具体题意解释在代码注释中

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
int cmp(const int& a,const int& b)
{
    return a>b;
}
//题目不好理解,是从给出的序列中选出最大的E,满足E天每天骑行距离都大于E。(不用按顺序)
int main()
{
    //freopen("test.txt","r",stdin);
    int n;
    scanf("%d",&n);
    int a[n];
    for(int i=0;i<n;++i)
    {
        scanf("%d",&a[i]);
    }
    sort(a,a+n,cmp);
    for(int len=n;len>=1;--len)
    {
        if(a[len-1]>len)
        {
            printf("%d
",len);
            return 0;
        }
    }
    printf("0
");
    return 0;
}
View Code

    1119题:有先序和后序求中序,题目很新颖,光想不太容易想清楚,最后画图和编码一起这样方便找规律。什么时候二叉树不唯一,什么时候唯一呢?那例题来说1 2 3 4 6 7 5和2 6 7 4 5 3 1,我们第一步可以得到当前父节点1。然后如何判断左右孩纸呢。

先序1后面那个就是下一个节点(2),后序1前面那个就是下一个节点(3),这时候你发现2和3不一样,说明什么呢--其实说明一个是左孩纸,一个是有孩纸。然后从先序中找右孩纸(3)的节点位置,然后我们可以找到左右孩纸的两颗树的序:左孩纸树的先序序列2,后序也是2,右孩纸的先序序列就是3 4 6 7 5,后序序列是6 7 4 5 3。然后不断重复以上步骤就好了。

再看另一个例子:1 2 3 4、2 4 3 1。为什么不唯一呢,找左右孩纸序列,左孩纸2 右孩纸3 4(先序),4 3(后序)。然后对右孩纸进行递归,你会发现根节点是3,孩纸节点只有一个(4),然后你就不知道他是属于左节点还是右节点了,所以不唯一。

所以结论:先序和后序求中序,要求必须是孩纸节点要么没有,要么是2个,不能有任意节点只有一个孩纸节点。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
struct Node
{
    int key;
    Node* left;
    Node* right;
    Node()
    {
        left = right = NULL;
    }
};
bool bOnly = true;
Node* CreateTree(int* pre,int *post,int len)
{
    Node *node = new Node();
    node->key = *pre;
    if(len != 1)
    {
        //printf("len=%d
",len);
        if(*(pre+1) == *(post+len-2))
        {
            bOnly = false;
            node->left = CreateTree(pre+1,post,len-1);
        }
        else
        {
            int rightkey = *(post+len-2);
            int rightindex = 0;
            for(;rightindex<len;++rightindex)
            {
                if(rightkey == *(pre+rightindex))
                {
                    break;
                }
            }
            node->left = CreateTree(pre+1,post,rightindex-1);
            node->right = CreateTree(pre+rightindex,post+rightindex-1,len-rightindex);
        }
    }
    return node;
}
bool bFirst = true;
void inorder_travel(Node* root)
{
    if(root == NULL) return;
    inorder_travel(root->left);
    if(bFirst) bFirst = false;
    else printf(" ");
    printf("%d",root->key);
    inorder_travel(root->right);
}
int main()
{
    //freopen("test.txt","r",stdin);
    int n;
    scanf("%d",&n);
    int pre[n],post[n];
    for(int i=0;i<n;++i)
        scanf("%d",&pre[i]);
    for(int i=0;i<n;++i)
        scanf("%d",&post[i]);
    Node* root = CreateTree(pre,post,n);
    if(bOnly)
    {
        printf("Yes
");
    }
    else
    {
        printf("No
");
    }
    inorder_travel(root);
    printf("
");
    return 0;
}
View Code

   1125题意还是搞错了。。。可以再做一遍看看。最后的四舍五入那一个可以忽略,好像没有case卡这个,直接转换成整型就行了。(可能他的case都是刚好整除的吧)

   1126题:1)题意比较绕,想复杂了;2)遍历所有节点判断错了。

  

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define N (510)
int n,m;
int Map[N][N];
int indegree[N];
bool bVis[N];
int sum=0;
void dfs(int curI,int istep)
{
    ++sum;
    for(int nextI=1;nextI<=n;++nextI)
    {
        if(Map[curI][nextI]&&!bVis[nextI])
        {
            bVis[nextI] = true;
            dfs(nextI,istep+1);
        }
    }
}
/*给定一个图,计算该图的每个结点的度
    若所有的节点的度均为偶数则为“Eulerian”,
    若恰好有两个为奇数则为“Semi-Eulerian”,
    其他为“Non-Eulerian”。
    需要判断是否是连通图。
    */
int main()
{
    //freopen("test.txt","r",stdin);
    scanf("%d%d",&n,&m);
    memset(Map,0,sizeof(Map));
    memset(indegree,0,sizeof(indegree));
    memset(bVis,0,sizeof(bVis));
    for(int i=0;i<m;++i)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        Map[a][b] = Map[b][a] = 1;
        ++indegree[a];
        ++indegree[b];
    }
    int iOddnum=0;
    for(int i=1;i<=n;++i)
    {
        if(indegree[i]%2)
        {
            ++iOddnum;
        }
        if(i>1) printf(" ");
        printf("%d",indegree[i]);
    }
    printf("
");
    bVis[1] = true;
    dfs(1,1);
    if(sum==n)
    {
        if(iOddnum==0) printf("Eulerian
");
        else if(iOddnum==2) printf("Semi-Eulerian
");
        else printf("Non-Eulerian
");
    }
    else
    {
        printf("Non-Eulerian
");
    }

    return 0;
}
View Code

   1131:题:简单dfs,刚开始理解错误,以为有公共线路,后来发现没有。最后一个case容易超时,是因为你把数组开太大。line[N][N],可以用map代替,key = i+j*N;

 #include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
#define N (10010)
struct ST
{
    int start;
    int stop;
    int line;
};
vector<int> vcMap[N];
//int line[N][N];
map<int,int> line;
bool bVis[N];
int iMinLen = N;
vector<ST> vs;
int iStartStop,iEndStop;
void dfs(int curI,int len,vector<ST>vi)
{
    if(curI==iEndStop)
    {
        if(len < iMinLen)
        {
            iMinLen = len;
            vs = vi;
        }
        else if(len==iMinLen&&vs.size()>vi.size())
        {
           vs = vi;
        }
        return;
    }
    if(len >= iMinLen) return;
    for(int i=0;i<vcMap[curI].size();++i)
    {
        int nextI = vcMap[curI][i];

        if(!bVis[nextI])
        {
            bVis[nextI] = true;
            int curLine = line[curI+nextI*N];
            bool bNeedAdd = true;
            if(vi.size()&&vi[vi.size()-1].line==curLine)
            {
                bNeedAdd = false;
            }

            if(bNeedAdd)
            {
                ST st;
                st.line = curLine;
                st.start = curI;
                st.stop =  nextI;
                vi.push_back(st);
            }
            else
            {
                vi[vi.size()-1].stop = nextI;
            }
            dfs(nextI,len+1,vi);
            if(bNeedAdd)
                vi.pop_back();
            else
            {
                vi[vi.size()-1].stop = curI;
            }
            bVis[nextI] = false;
        }
    }
}
int main()
{
    //freopen("test.txt","r",stdin);
    int n;
    scanf("%d",&n);
    int prestop;
    for(int i=0;i<n;++i)
    {
        int m;
        scanf("%d",&m);
        for(int j=0;j<m;++j)
        {
            int a;
            scanf("%d",&a);
            if(j==0) prestop = a;
            else
            {
                vcMap[prestop].push_back(a);
                vcMap[a].push_back(prestop);
                line[prestop+a*N] = i+1;
                line[a+prestop*N] = i+1;
                prestop = a;
            }
        }
    }
    int k;
    scanf("%d",&k);
    for(int i=0;i<k;++i)
    {
        memset(bVis,0,sizeof(bVis));
        iMinLen = N;
        scanf("%d%d",&iStartStop,&iEndStop);
        bVis[iStartStop] = 1;
        vs.clear();
        vector<ST> vi;
        dfs(iStartStop,0,vi);
        printf("%d
",iMinLen);
        for(int j=0;j<vs.size();++j)
        {
            printf("Take Line#%d from %04d to %04d.
",vs[j].line,vs[j].start,vs[j].stop);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/jlyg/p/7525244.html