小比赛(CodeForces 339D,POJ 1321,HDU 5078,HDU 2795,HDU 1385,HDU 1671,HDU 2923,POJ 2349)

题目链接:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=89134#overview

密码:

431


1.Xenia and Bit Operations

题目链接:

http://codeforces.com/problemset/problem/339/D

解题思路:

http://blog.csdn.net/piaocoder/article/details/47909667

AC代码:

#include <iostream>
#include <cstdio>
using namespace std;

const int maxn = 1<<17+5;
struct node{
    int l,r;
    int sum;
}tree[maxn<<2];
int a[maxn];

void build(int id,int l,int r,int op){
    tree[id].l = l;
    tree[id].r = r;
    if(l == r){
        tree[id].sum = a[l];
        return;
    }
    int mid = (l+r)>>1;
    build(id<<1,l,mid,-op);
    build(id<<1|1,mid+1,r,-op);
    if(op == 1)
        tree[id].sum = tree[id<<1].sum^tree[id<<1|1].sum;
    else
        tree[id].sum = tree[id<<1].sum|tree[id<<1|1].sum;
}

void update(int id,int x,int val,int op){
    if(tree[id].l == x && tree[id].r == x){
        tree[id].sum = val;
        return;
    }
    int mid = (tree[id].l+tree[id].r)>>1;
    if(x <= mid)
        update(id<<1,x,val,-op);
    else
        update(id<<1|1,x,val,-op);
    if(op == 1)
        tree[id].sum = tree[id<<1].sum^tree[id<<1|1].sum;
    else
        tree[id].sum = tree[id<<1].sum|tree[id<<1|1].sum;
}

int query(int id,int l,int r){
    if(tree[id].l == l && tree[id].r == r){
        return tree[id].sum;
    }
    int mid = (tree[id].l+tree[id].r)>>1;
    if(r <= mid)
        return query(id<<1,l,r);
    if(l > mid)
        return query(id<<1|1,l,r);
    return query(id<<1,l,mid)^query(id<<1|1,mid+1,r);
}

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        int num = 1<<n,op;
        for(int i = 1; i <= num; i++)
            scanf("%d",&a[i]);
        if(n&1)
            op = -1;//或
        else
            op = 1;//异或
        build(1,1,num,op);
        int a,b;
        while(m--){
            scanf("%d%d",&a,&b);
            update(1,a,b,op);
            printf("%d\n",query(1,1,num));
        }
    }
    return 0;
}



2.棋盘问题

题目链接:

http://poj.org/problem?id=1321

解题思路:

http://blog.csdn.net/piaocoder/article/details/47909867

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int n,m;
char node[10][10];
int vis[10];
int ans;

void dfs(int row,int sum){
    if(sum == m){
        ans++;
        return;
    }
    if(row > n)
        return;
    for(int j = 1; j <= n; j++){
        if(node[row][j] == '#' && !vis[j]){
            vis[j] = 1;
            dfs(row+1,sum+1);
            vis[j] = 0;
        }
    }
    dfs(row+1,sum);
    //这步很关键,想上去了,这题就成了水题,想不上去的话。。。
    //当k<n时,row在等于n之前就可能已经把全部棋子放好
    //又由于当全部棋子都放好后的某个棋盘状态已经在前面循环时记录了
    //因此为了处理多余行,令当前位置先不放棋子,搜索在下一行放棋子的情况
}

int main(){
    while(~scanf("%d%d",&n,&m)){
        if(n+m < 0)
            break;
        for(int i = 1; i <= n; i++)
            scanf("%s",node[i]+1);
        ans = 0;
        memset(vis,0,sizeof(vis));
        dfs(1,0);
        printf("%d\n",ans);
    }
    return 0;
}



3.Osu!

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5078

解题思路:

先将每个点按时间排个序,再找距离/时间差的最大值

AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

struct node{
    int t;
    double x,y;
}no[1005];

double dis(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

bool cmp(node a,node b){
    return a.t < b.t;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        double sum = 0;
        for(int i = 1; i <= n; i++)
            scanf("%d%lf%lf",&no[i].t,&no[i].x,&no[i].y);
        sort(no+1,no+n+1,cmp);
        for(int i = 2; i <= n; i++){
            sum = max(sum,dis(no[i].x,no[i].y,no[i-1].x,no[i-1].y)/(no[i].t-no[i-1].t));
        }
        printf("%.10lf\n",sum);
    }
    return 0;
}



4.Billboard

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2795

解题思路:

http://blog.csdn.net/piaocoder/article/details/47910001

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 200005;
struct node{
    int l,r;
    int num;
}tree[N<<2];
int h,w,n;

void build(int id,int l,int r){
    tree[id].l = l;
    tree[id].r = r;
    tree[id].num = w;
    if(l == r)
        return ;
    int mid = (l+r)>>1;
    build(id<<1,l,mid);
    build(id<<1|1,mid+1,r);
}

int query(int id,int len){
    if(tree[id].l == tree[id].r){
        tree[id].num -= len;
        return tree[id].l;
    }
    else{
        int sum1 = 0,sum2 = 0;
        if(len <= tree[id<<1].num)
            sum1 = query(id<<1,len);
        else if (len <= tree[id<<1|1].num)
            sum2 = query(id<<1|1,len);
        tree[id].num = max(tree[id<<1].num,tree[id<<1|1].num);
        return sum1+sum2;
    }
}

int main(){
    while(~scanf("%d%d%d",&h,&w,&n)){
        if(h > n)
            h = n;
        build(1,1,h);
        int x;
        for(int i = 1; i <= n; i++){
            scanf("%d",&x);
            if(tree[1].num >= x)
                printf("%d\n",query(1,x));
            else
                printf("-1\n");
        }
    }
    return 0;
}



5.Minimum Transport Cost

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1385

解题思路:

http://blog.csdn.net/piaocoder/article/details/47910271

AC代码:

#include <iostream>
#include <cstdio>
using namespace std;

const int INF = 0xfffffff;
const int N = 105;
int n;
int edge[N][N];
int path[N][N];
int charge[N];

void floyd(){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                if(edge[i][k] != INF && edge[k][j] != INF){
                    int tmp = edge[i][k]+edge[k][j]+charge[k];
                    if(edge[i][j] > tmp){
                        edge[i][j] = tmp;
                        path[i][j] = path[i][k];
                    }
                    else if(edge[i][j] == tmp && path[i][j] > path[i][k])
                        path[i][j] = path[i][k];
                }
            }
        }
    }
}

int main(){
    while(scanf("%d",&n),n){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                scanf("%d",&edge[i][j]);
                if(edge[i][j] == -1)
                    edge[i][j] = INF;
                path[i][j] = j;
            }
        }
        for(int i = 1; i <= n; i++)
            scanf("%d",&charge[i]);

        floyd();
        int from,to;
        while(scanf("%d%d",&from,&to)){
            if(from == -1 && to == -1)
                break;
            printf("From %d to %d :\n",from,to);
            printf("Path: ");
            int cur = from;
            printf("%d",cur);
            while(cur != to){
                printf("-->%d",path[cur][to]);
                cur = path[cur][to];
            }
            puts("");
            printf("Total cost : %d\n\n", edge[from][to]);
        }
    }
    return 0;
}



6.Phone List

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1671

解题思路:

http://blog.csdn.net/piaocoder/article/details/47951011

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

char str[10005][15];

struct node
{
    int cnt;
    struct node *next[10];
    node()
    {
        cnt=0;
        memset(next,0,sizeof(next));
    }
};

node *root = NULL;

void buildtrie(char *s)
{
    node *p=root;
    node *tmp=NULL;
    int i,l=strlen(s);
    for(i=0;i<l;i++)
    {
        if(p->next[s[i]-'0']==NULL)
        {
            tmp=new node;
            p->next[s[i]-'0']=tmp;
        }
        p=p->next[s[i]-'0'];
        p->cnt++;
    }
}

bool findtrie(char *s)
{
    node *p=root;
    int i,l=strlen(s);
    for(i=0;i<l;i++)
        p=p->next[s[i]-'0'];
    if(p->cnt != 1)
        return true;
    return false;
}

void del(node *root)
{
	for(int i=0;i<10;i++)
		if(root->next[i])
            del(root->next[i]);
    delete(root);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        root = new node;
        int n;
        scanf("%d",&n);
        for(int i = 1; i <= n; i++){
            scanf("%s",str[i]);
            buildtrie(str[i]);
        }
        int flag = 1;
        for(int i = 1; i <= n; i++){
            if(findtrie(str[i])){
                flag = 0;
                break;
            }
        }
        if(flag)
            printf("YES\n");
        else
            printf("NO\n");
        del(root);
    }
    return 0;
}



7.Einbahnstrasse

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2923

解题思路:

题意:一开始给出三个数字,n,c,m,代表城市数,破车数,道路数

然后给你m条路线,箭头为方向,数字为花费,然后求出从公司派出车,到每个城市回收破车的最小花费,需要注意每辆车只能回收

一辆破车

用floyd求最短路。。。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#define INF 0xfffffff
using namespace std;

int n,c,m;
int edge[110][110];
string str[1005];
map<string,int> mm;

void floyd(){
    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                edge[i][j] = min(edge[i][j],edge[i][k]+edge[k][j]);
}

int main(){
    int t = 1;
    while(scanf("%d%d%d",&n,&c,&m),n+c+m){
        mm.clear();
        for(int i = 1; i <= n; i++){
            edge[i][i] = 0;
            for(int j = 1; j < i; j++)
                edge[i][j] = edge[j][i] = INF;
        }
        for(int i = 0; i <= c; i++)
            cin>>str[i];
        string s1,s2;
        char op1,op2,tmp1,tmp2;
        int num,id = 1;
        for(int i = 0; i < m; i++){
            cin>>s1>>op1>>tmp1>>num>>tmp2>>op2>>s2;
            if(!mm[s1])
                mm[s1] = id++;
            if(!mm[s2])
                mm[s2] = id++;
            if(op1 == '<')
                edge[mm[s2]][mm[s1]] = min(edge[mm[s2]][mm[s1]],num);
            if(op2 == '>')
                edge[mm[s1]][mm[s2]] = min(edge[mm[s1]][mm[s2]],num);
        }
        floyd();
        int start = mm[str[0]];
        int sum = 0;
        for(int i = 1; i <= c; i++)
            sum += edge[start][mm[str[i]]]+edge[mm[str[i]]][start];
        printf("%d. %d\n",t++,sum);
    }
    return 0;
}



8.Arctic Network

题目链接:

http://poj.org/problem?id=2349

解题思路:

http://blog.csdn.net/piaocoder/article/details/47910955

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define INF 0xfffffff
using namespace std;

struct node{
    double x,y;
}no[505];
int s,p,ans;
double edge[505][505];
double dis[505];
double temp[505];
int vis[505];

double dist(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

bool cmp(double x,double y){
    return x > y;
}

void prim(int cur)
{
    int i, j, tmp;
    memset(vis, 0, sizeof(vis));
    for(i = 1; i <= p; i++)
        dis[i] = edge[cur][i];
    vis[cur] = 1;
    for(i = 2; i <= p; i++)
    {
        double Min = INF;
        for(j = 1; j <= p; j++)
        {
            if(!vis[j] && dis[j] < Min)
                Min = dis[tmp = j];
        }
        vis[tmp] = 1;
        temp[ans++] = Min;
        for(j = 1; j <= p; j++)
        {
            if(!vis[j] && dis[j] > edge[tmp][j])
                dis[j] = edge[tmp][j];
        }
    }
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&s,&p);
        for(int i = 1; i <= p; i++)
            scanf("%lf%lf",&no[i].x,&no[i].y);
        for(int i = 1; i <= p; i++){
            edge[i][i] = 0;
            for(int j = 1; j < i; j++){
                edge[i][j] = edge[j][i] = dist(no[i].x,no[i].y,no[j].x,no[j].y);
            }
        }
        ans = 0;
        prim(1);
        sort(temp,temp+ans,cmp);
        printf("%.2f\n",temp[s-1]);
    }
    return 0;
}


你可能感兴趣的:(ACM,小比赛)