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;
}
题意: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;
}