The 36th ACM/ICPC Asia Regional Dalian Site —— Online Contest(套题HDU4001-4010)

HDU4001:To Miss Our Children Time

题意:堆积木,积木有4个参数,分别为长,宽,高,要求。要求有三种,一种是在上面的积木的长和宽要大于等于下面接触的,第二种是上面的积木长和宽要大于等于下面接触的,但是面积不能相同,第三种就是上面的积木的长和宽要大于下面接触的。一共有n个积木,问最多能堆多高。

思路:简单DP。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn = 1000+10;
struct block{
    int a,b,c,d;
    block(int a,int b,int c,int d):a(a),b(b),c(c),d(d){}
};
vector<block> vb;
int n;
ll dp[maxn];

ll dfs(int x){
    if(dp[x] != -1) return dp[x];
    ll ans = vb[x].c;
    for(int i = 0; i < n; i++){
        if(i==x) continue;
        if(vb[x].d==0){
            if(vb[i].a <= vb[x].a && vb[i].b <= vb[x].b){
                ans = max(ans,dfs(i)+vb[x].c);
            }
        }else if(vb[x].d ==1){
            if((vb[i].a <= vb[x].a && vb[i].b < vb[x].b )|| (vb[i].a < vb[x].a && vb[i].b <= vb[x].b) ){
                ans = max(dfs(i)+vb[x].c,ans);
            }
        }else{
            if(vb[i].a < vb[x].a && vb[i].b < vb[x].b){
                ans = max(ans,dfs(i)+vb[x].c);
            }
        }
    }
    return dp[x] = ans;

}
int main(){

    while(~scanf("%d",&n) && n){
        vb.clear();
        memset(dp,-1,sizeof dp);
        for(int i = 0; i < n; i++){
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(a > b) swap(a,b);
            vb.push_back(block(a,b,c,d));
        }
        ll ans = 0;
        for(int i = 0; i < n; i++){
            ans = max(ans,dfs(i));
        }
        cout<<ans<<endl;
    }
    return 0;
}


HDU4002:Find the maximum

题意:从2~N中找到  最大的 n使得  n/phi(n) 最大。

思路:直接从欧拉函数定义分析,最后的结果就是要使n质因数越多越好。JAVA大数搞定。

import java.math.BigInteger;
import java.util.Scanner;


public class Main {

	private static Scanner scan;

	public static void main(String[] args) {
		scan = new Scanner(System.in);
		int ncase = scan.nextInt();
		boolean []isPrime = new boolean[10010];
		for(int i = 0; i < 10010; i++){
			isPrime[i] = false;
		}
		BigInteger []dp = new BigInteger[10010];
		int []prime = new int[10010];
		int cnt = 1;
		for(int i = 2; i < 10000; i++){
			if(!isPrime[i]){
				prime[cnt++] = i;
				for(int j = i*i; j < 10000; j+=i){
					isPrime[j] = true;
				}	
			}
		}
		dp[0] = BigInteger.ONE;
		for(int i = 1; i < cnt; i++){
			dp[i] = dp[i-1].multiply(BigInteger.valueOf(prime[i]));
		}
		while(ncase-->0){
			BigInteger n = scan.nextBigInteger();
			int ans = 0;
			int  k = 0;
			for(int i = 1; i < cnt; i++){
				if(dp[i].compareTo(n)>0){
					ans = i;
					break;
				}
			}
			System.out.println(dp[ans-1]);
		}
	}

}


HDU4004:The Frog's Games

题意:青蛙跳过河,河宽L,有n个石头,最多条跳m次,问满足条件的最大跳跃距离中的最小值。

思路:二分答案+二分石头

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 500000+10;
int stone[maxn];
int L,n,m;
int dis[maxn];
bool can(int x){
    int s=x;
    int sum=1;
    while(s < L){
        sum++;
        if(sum > m) return false;
        int tt = lower_bound(stone,stone+n+2,s)-stone;
        if(stone[tt] > s){
            tt--;
        }
        s = stone[tt]+x;

    }
    return true;
}

int main(){

    while(~scanf("%d%d%d",&L,&n,&m)){
        for(int i = 1; i <= n; i++) scanf("%d",&stone[i]);
        stone[0] = 0;
        stone[n+1] = L;
        sort(stone,stone+n+2);
        int l = 0,r = L;
        while(l <= r){
            int mid = (l+r)>>1;
            if(can(mid)){
                r = mid-1;
            }else{
                l = mid+1;
            }

        }
        cout<<l<<endl;



    }
    return 0;
}


HDU4006:The kth great number

题意:n次操作,操作分两种,一种是写一个数,一种查询第k大数。 (1=<k<=n<=1000000)

思路:优先队列维护前k大数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
int n,k;
priority_queue<int,vector<int>,greater<int> >pq;
int main(){

    while(~scanf("%d%d",&n,&k)){
        while(!pq.empty()) pq.pop();
        char op[20];
        int a;
        while(n--){
            scanf("%s",op);
            if(op[0]=='I'){
                scanf("%d",&a);
                if(pq.size() == k){
                    if(a > pq.top()){
                        pq.pop();
                        pq.push(a);
                    }
                }else{
                    pq.push(a);
                }
            }else{
                cout<<pq.top()<<endl;

            }
        }

    }
    return 0;
}

HDU4007:Dave

题意:xoy坐标系有n个点,问你用一个边长为r的正方形去框点,最多能框多少个点

思路:水题,暴力二维扫描线

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
using namespace std;
struct node{
    int x,y;
    node(int x,int y):x(x),y(y){}
};
bool cmp1(node a,node b){
    if(a.x != b.x) return a.x < b.x;
    else return a.y < b.y;
}
bool cmp2(node a,node b){
    if(a.y != b.y) return a.y < b.y;
    else return a.x < b.x;
}
vector<node> vn,nn;
int n,r;
int ans;
int main(){

    while(~scanf("%d%d",&n,&r)){
        vn.clear();
        ans = 0;
        for(int i = 0; i < n; i++){
            int a,b;
            scanf("%d%d",&a,&b);
            vn.push_back(node(a,b));
        }
        sort(vn.begin(),vn.end(),cmp1);
        for(int i = 0; i < n; i++){
            int j = i;
            nn.clear();
            while(j < vn.size() &&vn[j].x  <= vn[i].x+r){
                nn.push_back(vn[j]);
                j++;
            }
            sort(nn.begin(),nn.end(),cmp2);
            for(int j = 0; j < nn.size(); j++){
                int k = j;
                while(k < nn.size() && nn[k].y <= nn[j].y+r) k++;
                ans = max(ans,k-j);
            }
        }
        printf("%d\n",ans);

    }
    return 0;
}





HDU4009:Transfer water

题意:有n个房子(n<=1000),有三个参数x,y,z对应它的坐标,每个房子可以自己挖个井花费为X*x,也可以从其他房子引水管如果水源的高度低于自身高度,那么花费为曼哈顿距离*y+z,否则花费为曼哈顿距离*y。问所有用户都能有水用的最小话费。

思路:有向图的最小生成树即最小树形图,将可以引水管的房子连边,以及自己可以挖井,将自身与一个超级源点(根节点)连边,不存在无解的情况.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
using namespace std;
const int maxn = 1000+10;
const int inf = 1<<25;
struct house{
    int a,b,c;
    house(){}
};
vector<house> vh;
struct edge{
    int u,v,w;
    edge(int u,int v,int w):u(u),v(v),w(w){}
};
vector<edge>E;
int nume;
int n,x,y,z;
int ans;
int ID[maxn],pre[maxn],to[maxn],inw[maxn];

void addedge(int u,int v,int w){
    E.push_back(edge(u,v,w));
}

inline int getDist(int x,int y){
    return abs(vh[x].a-vh[y].a)+abs(vh[x].b-vh[y].b)+abs(vh[x].c-vh[y].c);
}

void ZhuLiu(int rt){
    int t,idx,u,v;
    while(true){
        for(int i = 0; i < n; i++){
            inw[i] = inf;
            ID[i] = -1;
            to[i] = -1;
        }
        for(int i = 0; i < nume; i++){
            u = E[i].u;
            v = E[i].v;
            if(E[i].w < inw[v] && u != v){
                inw[v] = E[i].w;
                pre[v] = u;
            }
        }
        inw[rt] = 0;
        idx = 0;
        for(int i = 0; i < n; i++){
            t = i;
            ans += inw[i];
            while(to[t]!=i && ID[t]==-1 && t!=rt){
                to[t] = i;
                t = pre[t];
            }
            if(t!=rt && ID[t]==-1){
                for(int u=pre[t]; u!=t; u=pre[u]){
                    ID[u] = idx;
                }
                ID[t] = idx++;
            }
        }
        if(idx==0) break;
        for(int i = 0; i < n; i++){
            if(ID[i]==-1) ID[i] = idx++;
        }
        for(int i = 0; i < nume; i++){
            u = E[i].u;
            v = E[i].v;
            E[i].w -= inw[v];
            E[i].u = ID[u];
            E[i].v = ID[v];

        }
        n = idx;
        rt = ID[rt];
    }
    printf("%d\n",ans);
}

void init(){
    ans = 0;
    vh.clear();
    vh.resize(n+1);
    E.clear();
}

int main(){
    while(~scanf("%d%d%d%d",&n,&x,&y,&z) && n+x+y+z){
        init();
        for(int i = 1; i <= n; i++){
            scanf("%d%d%d",&vh[i].a,&vh[i].b,&vh[i].c);
            addedge(0,i,x*vh[i].c);
        }
        for(int i = 1; i <= n; i++){
            int k,t;
            scanf("%d",&k);
            while(k--){
                scanf("%d",&t);
                if(t==i) continue;
                if(vh[t].c > vh[i].c){
                    addedge(i,t,getDist(t,i)*y+z);
                }else{
                    addedge(i,t,getDist(t,i)*y);
                }
            }
        }
        ++n;
        nume = E.size();
        ZhuLiu(0);
    }
    return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值