2015-07-18 随意刷几道题机试题(最大上升子序列和、并查集、蚂蚁下落等问题)

/*
第一题:简单题 http://ac.jobdu.com/problem.php?pid=1465
求解两数是否互质,二重循环,辗转相除法判断即可。
复杂度:O(n^2)
 
代码:


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
using namespace std;
#define N 10010

int f[N];

int check(int a,int b){
    //辗转相除法、计算最大公约数   为1时表示两者互质、否则不互质,即指两者存在共同约数。
    if(a<b) swap(a,b);
    while(a>1 && b>1){
        if(a%b==0) return 1;
        else{
            int t = b;
            b = a%b;
            a = t;
        }
    }
    return 0;
}
int main() {
    freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
    int n;
    while(scanf("%d",&n) && n){
        for(int i=0;i<n;i++) scanf("%d",&f[i]);
        int num=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<n && j!=i;j++){
                if(!check(f[i],f[j])) num++;
            }
        }
        printf("%d\n",num);

    }
    return 0;
}
*/


/*
第二题:最大上升子序列的进化版、求最大生生子序列和,一样,简单DP
 http://ac.jobdu.com/problem.php?pid=1480
dp时将长度的累加与判断,转换成和的累加与判断即可。
复杂度:O(n^2)

求和最大可能为1000*10000 = 10^7  在int范围内

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
using namespace std;
#define N 10010

int f[N];
int num[N];
int main() {
    freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++) scanf("%d",&f[i]);
        memset(num,0,sizeof(num));
        num[0] = f[0];
        for(int i=1;i<n;i++){
            num[i] = f[i]; //这句一定记得要写!  否则10、7、8这种情况会错,具体手算一遍即知
            for(int j=i-1;j>=0;j--){
                if(f[i]>f[j] && f[i] + num[j] > num[i]){  //如果当前值大于j位的数字,并且和大于当前计算得到的num[i]
                    num[i] = f[i] + num[j];
                }
            }
        }

        int maxc = -1;
        for(int i=0;i<n;i++)
            if(num[i]>maxc) maxc = num[i];
        printf("%d\n",maxc);
    }
    return 0;
}
*/


/*
第三题:树结构判断  http://ac.jobdu.com/problem.php?pid=1481
核心:题意 + 并查集的判断(判断是否只有一棵树)
提示: 一直以为空树不是树!  因此WA了好多发
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
using namespace std;
#define N 10010

int nodes[N];
int father[N];
int vis[N];
void init(){
    memset(nodes,0,sizeof(nodes));
    memset(father,0,sizeof(father));
    memset(vis,0,sizeof(vis));
    for(int i=0;i<N;i++){
        father[i] = i;
    }
}
int find(int x){
    return x==father[x] ? x : find(father[x]);
}
int num1,num2;
void union_nodes(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx!=fy){
        father[fx] = fy;
    }
    else{ //属于同一集合的时候  意味着有错误
        num1++;  //记录合并了多少次
    }
}
int k=1;
int main() {
    freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
    int a,b;
    while(scanf("%d %d",&a,&b) && a>=0 && b>=0){
        init();
        int edge = 0;
        int flag = 0;
        num1 = 0;
        while(1){
            if(a==0 || b==0) break;

            if(find(b)==b && find(a)!=b) //注意这里是有顺序的! 后者向前者合并
                father[b] = a;
            else flag=1;
            vis[a]=1;vis[b]=1;
            edge++;
            scanf("%d %d",&a,&b);
        }

        //并查集判断,之前NUM记录了全部的合并次数   本来
        int num=0;
        for(int i=0;i<N;i++){
            if(vis[i]) num++;
        }
        if(num!=0 && num!=edge+1) flag=1;


        printf("Case %d ",k++);
        if(flag){
            printf("is not a tree.\n");
        }else
            printf("is a tree.\n");
    }
    return 0;
}

*/


/*
第四题:谁是你的潜在朋友 http://ac.jobdu.com/problem.php?pid=1156
水题
核心: 记录每本书的入度,每多一个人喜欢,入度+1, 判断每个人的时候,看其最喜欢数目的入度为多少,-1即为其朋友数。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
using namespace std;
#define N 10010

int f[N];
int in[N];
int main() {
    //freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF){
        memset(in,0,sizeof(in));
        for(int i=0;i<n;i++){
            scanf("%d",&f[i]);
            in[f[i]]++;
        }
        for(int i=0;i<n;i++){
            if(in[f[i]]-1==0) printf("BeiJu\n");
            else printf("%d\n",in[f[i]]-1);
        }

    }
    return 0;
}
*/



/*
第五题:买房子 http://ac.jobdu.com/problem.php?pid=1158
简单题
数学题: 求解一次函数与指数在正半轴是否存在交点、(year<=20) 存在输入交点横坐标、否则输出Impossible

 代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
using namespace std;
#define N 10010

int main() {
    //freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF){
        double tot = 200.0;
        int year=1;
        int flag=1;
        while(1){
            if(year>20) {flag=0;break;}
            tot *= (1.0+(double)m/100);
//            printf("tot = %lf     num  = %lf  \n",tot,(year+1)*n - tot );
            if((year+1)*n - tot >=0){
                flag = year;
                break;
            }
            year++;
        }
        if(flag) printf("%d\n",flag+1);
        else printf("Impossible\n");

    }
    return 0;
}
 */


/*
第六题:坠落的蚂蚁 http://ac.jobdu.com/problem.php?pid=1159
算是一个思考题,其实把握到本质就好
 从样例可以看出,对蚂蚁A最终下落时间有影响的其它蚂蚁,仅为面向蚂蚁A走向的所有蚂蚁。
 设:蚂蚁A左侧面向其的蚂蚁数为B,蚂蚁A右侧面向其的蚂蚁数为C
 如果B==C,蚂蚁A不会掉下;
 否则若B>C,找到蚂蚁A左侧第B-C只蚂蚁D,100-蚂蚁D的位置,即为结果;
    若C>B,找到蚂蚁A右侧第C-B只蚂蚁E,蚂蚁E的位置即为结果。

 
 提示:一开始思路想法都没错,但是在找位置时有点差错:
 对于数据:
 5
 20 1
 30 -1
 40 1
 50 0
 60 -1
 过不了,之前的代码找到位置30的地方,没有判断当前蚂蚁是否向右行走。(在蚂蚁A右侧时要判断是否向左行走)
 



#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
using namespace std;
#define N 10010
typedef struct LNode{
    int location;
    int flag;
}LNode;
LNode node[N];
int cmd(LNode x,LNode y){
    return x.location < y.location;
}
int main() {
    //freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF){
        memset(node,0,sizeof(node));
        for(int i=0;i<n;i++) scanf("%d %d",&node[i].location,&node[i].flag);
        sort(node,node+n,cmd);
        int mid = -1;
        for(int i=0;i<n;i++){
            if(node[i].flag==0){
                mid = i;break;
            }
        }
        int left=0,right=0;
        for(int i=mid-1;i>=0;i--){
            if(node[i].flag==1) left++;
        }
        for(int i=mid+1;i<n;i++){
            if(node[i].flag==-1) right++;
        }
//        printf("left = %d right = %d\n",left,right);
        if(left==right) printf("Cannot fall!\n");
        else{
            if(left>right){
                int ans;
                for(int i=mid-1;i>=0;i--){
                    if(right==0){
                        ans = i;break;
                    }
                    if(node[i].flag==1){
                        right--;
                    }
                }
                while(node[ans].flag!=1) ans--;  //后来加上的代码才过
                printf("%d\n",100-node[ans].location);
            }else{
                int ans;
                for(int i=mid+1;i<n;i++){
                    if(left==0){
                        ans = i;break;
                    }
                    if(node[i].flag==-1) left--;
                }
                while(node[ans].flag!=-1) ans++; //后来加上的代码才过
                printf("%d\n",node[ans].location);
            }

        }
    }
    return 0;
}
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值