HDU - 2102(bfs.)、HDU - 1394(线段树.)、HDU - 1156(树状数组+离散化.)、POJ - 2253(最小生成树.)、POJ - 1797(最小生成树+dp.)

Time limit1000 ms
Memory limit32768 kB
OSWindows

题目:
可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验。魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的肉也能长生不老。年迈的国王正是心急如焚,告招天下勇士来拯救公主。不过公主早已习以为常,她深信智勇的骑士LJ肯定能将她救出。
现据密探所报,公主被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),公主的位置用P表示,时空传输机用#表示,墙用表示,平地用.表示。骑士们一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那骑士们就会被撞死。骑士们在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。
Input
输入的第一行C表示共有C个测试数据,每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小N
M(1 <= N,M <=10)。T如上所意。接下去的前NM表示迷宫的第一层的布置情况,后NM表示迷宫第二层的布置情况。
Output
如果骑士们能够在T时刻能找到公主就输出“YES”,否则输出“NO”。
Sample Input
1
5 5 14
S*#*.
.#…

****.
…#.

.P
#.

**
.
*.#…
Sample Output
YES

代码:

#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
 
struct node
{
    int x,y,floor;
    int step;
};
 
int t,n,m,lim;
int s[3],e[3];
int to[4][2] = {1,0,0,1,-1,0,0,-1};
char map[2][15][15];
int vis[2][15][15];
 
int check(int floor,int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m)
        return 1;
    if(map[floor][x][y]=='*')
        return 1;
    return 0;
}
 
void bfs()
{
    memset(vis,0,sizeof(vis));
    node a,next;
    queue<node> Q;
    int i,j,k;
    a.floor = s[0];
    a.x = s[1];
    a.y = s[2];
    a.step = 0;
    vis[s[0]][s[1]][s[2]] = 1;
    Q.push(a);
    while(!Q.empty())
    {
        a = Q.front();
        Q.pop();
        if(a.floor == e[0] && a.x == e[1] && a.y == e[2])
        {
            printf("YES\n");
            return ;
        }
        if(a.step>=lim)
            break;
        for(i = 0; i<4; i++)
        {
            next = a;
            next.x+=to[i][0];
            next.y+=to[i][1];
            next.step++;
            if(check(next.floor,next.x,next.y))
                continue;
            if(vis[next.floor][next.x][next.y])
                continue;
            vis[next.floor][next.x][next.y] = 1;
            if(map[next.floor][next.x][next.y] == '#')
            {
 
                next.floor=!next.floor;
                if(check(next.floor,next.x,next.y))
                    continue;
                if(vis[next.floor][next.x][next.y])
                    continue;
                if(map[next.floor][next.x][next.y] == '*' || map[next.floor][next.x][next.y] == '#')
                    continue;
                vis[next.floor][next.x][next.y] = 1;
            }
            if(next.floor == e[0] && next.x == e[1] && next.y == e[2])
            {
                printf("YES\n");
                return ;
            }
            Q.push(next);
        }
    }
    printf("NO\n");
}
 
int main()
{
    int i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&lim);
        for(k = 0; k<2; k++)
        {
            for(i = 0; i<n; i++)
            {
                scanf("%s",map[k][i]);
                for(j = 0; j<m; j++)
                {
                    if(map[k][i][j] == 'S')
                    {
                        s[0] = k,s[1] = i,s[2] = j;
                    }
                    else if(map[k][i][j] == 'P')
                    {
                        e[0] = k,e[1] = i,e[2] = j;
                    }
                }
            }
        }
        bfs();
    }
 
    return 0;
}

Time limit1000 ms
Memory limit32768 kB
OSWindows

题目:
The inversion number of a given number sequence a1, a2, …, an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.

For a given sequence of numbers a1, a2, …, an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:

a1, a2, …, an-1, an (where m = 0 - the initial seqence)
a2, a3, …, an, a1 (where m = 1)
a3, a4, …, an, a1, a2 (where m = 2)

an, a1, a2, …, an-1 (where m = n-1)

You are asked to write a program to find the minimum inversion number out of the above sequences.
Input
The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
Output
For each case, output the minimum inversion number on a single line.
Sample Input
10
1 3 6 9 0 8 5 7 4 2
Sample Output
16

代码:

#include <iostream>
#include <cmath>
using namespace std;
 
struct Tree
{
    int l,r,mid;
    int sum;
}T[15555];
 
int min(int a,int b)
{
    return a>b?b:a;
}
 
void build(int l,int r,int k)
{
    T[k].l = l;
    T[k].r = r;
    T[k].mid = (l+r) >> 1;
    T[k].sum = 0;
    if (l == r)
    return ;
    build(l,T[k].mid,k << 1);
    build(T[k].mid+1,r,k<<1|1);
}
 
void insert(int aim,int l,int r,int k)
{
    if(T[k].l == aim && T[k].r == aim)
    {
        T[k].sum++;
        return;
    }
    if(aim <= T[k].mid)
    insert(aim,l,T[k].mid,k<<1);
    else
    insert(aim,T[k].mid+1,r,k<<1|1);
    T[k].sum = T[k<<1].sum + T[k<<1|1].sum;
}
 
int ans;
void search(int l,int r,int k)
{
    if(T[k].l == l && T[k].r == r)
    {
        ans+=T[k].sum;
        return ;
    }
    if(r <= T[k].mid)
    search(l,r,k<<1);
    else if(l > T[k].mid)
    search(l,r,k<<1|1);
    else
    {
        search(l,T[k].mid,k<<1);
        search(T[k].mid+1,r,k<<1|1);
    }
}
 
int main()
{
    int n,i,num[5005],sum,text;
    while(cin >> n)
    {
        build(1,n,1);
        sum = 0;
        for(i = 0;i<n;i++)
        {
            cin >> num[i];
            num[i]++;
            ans = 0;
            if(num[i]!=n)
            search(num[i]+1,n,1);
            sum += ans;
            insert(num[i],1,num[i],1);
        }
        text = sum;
        for(i = n-1;i>=0;i--)
        {
            sum = sum - (n-num[i])+(num[i]-1);
            text = min(text,sum);
        }
        cout << text << endl;
    }
 
    return 0;
}

Time limit10000 ms
Memory limit32768 kB
OSWindows

题目:
Stan and Ollie play the game of Odd Brownie Points. Some brownie points are located in the plane, at integer coordinates. Stan plays first and places a vertical line in the plane. The line must go through a brownie point and may cross many (with the same x-coordinate). Then Ollie places a horizontal line that must cross a brownie point already crossed by the vertical line.
Those lines divide the plane into four quadrants. The quadrant containing points with arbitrarily large positive coordinates is the top-right quadrant.

The players score according to the number of brownie points in the quadrants. If a brownie point is crossed by a line, it doesn’t count. Stan gets a point for each (uncrossed) brownie point in the top-right and bottom-left quadrants. Ollie gets a point for each (uncrossed) brownie point in the top-left and bottom-right quadrants.

Stan and Ollie each try to maximize his own score. When Stan plays, he considers the responses, and chooses a line which maximizes his smallest-possible score.
Input
Input contains a number of test cases. The data of each test case appear on a sequence of input lines. The first line of each test case contains a positive odd integer 1 < n < 200000 which is the number of brownie points. Each of the following n lines contains two integers, the horizontal (x) and vertical (y) coordinates of a brownie point. No two brownie points occupy the same place. The input ends with a line containing 0 (instead of the n of a test).
Output
For each input test, print a line of output in the format shown below. The first number is the largest score which Stan can assure for himself. The remaining numbers are the possible (high) scores of Ollie, in increasing order.
Sample Input
11
3 2
3 3
3 4
3 6
2 -2
1 -3
0 0
-3 -3
-3 -2
-3 -4
3 -7
0
Sample Output
Stan: 7; Ollie: 2 3;

代码:

#include<cstdio>
#include<string.h>
#include<set>
#include<algorithm>
using namespace std;
 
const int maxn=200005;
int c[maxn];
int up[maxn];
int down[maxn];
int right[maxn];
int left[maxn];
int large[maxn];
int id[maxn];
int n;
 
int lowbit(int i){return i&(-i);}
 
void add(int x,int v){
	while(x<maxn){
		c[x]+=v;
		x+=lowbit(x);
	}
}
 
int getsum(int x){
	int res=0;
	while(x>0){
		res+=c[x];
		x-=lowbit(x);
	}
	return res;
}
 
struct node{
	int x,y,id;
}p[maxn];
 
void init(void){
	for(int i=0;i<=n;i++){
		c[i]=large[i]=up[i]=down[i]=left[i]=right[i]=0;
	}
}
 
int cmp1(node a,node b){
	if(a.x!=b.x)return a.x<b.x;
	return a.y<b.y;
}
 
int cmp2(node a,node b){
	if(a.y!=b.y)return a.y<b.y;
	return a.x<b.x;
}
 
int main(){
	while(~scanf("%d",&n),n){
		for(int i=0;i<n;i++){
			scanf("%d%d",&p[i].x,&p[i].y);
			p[i].id=i;
		}
		init();
		sort(p,p+n,cmp2);//先对y排序
		for(int i=1;i<n;i++){
			if(p[i].y==p[i-1].y ){
				left[p[i].id ]=left[p[i-1].id ]+1;
			}
			if(p[n-i-1].y==p[n-i].y ){
				large[p[n-i-1].id]=large[p[n-i].id];
				right[p[n-i-1].id]=right[p[n-i].id]+1;
			}else{
				large[p[n-i-1].id]=i;
			}
		}
		int k=1;
		id[p[0].id ]=k;
		for(int i=1;i<n;i++){//对y离散化
			if(p[i].y==p[i-1].y){
				id[p[i].id]=k;
			}else{
				id[p[i].id]=++k;
			}
		}
		sort(p,p+n,cmp1);
		for(int i=1;i<n;i++){
			if(p[i].x==p[i-1].x){
				down[p[i].id ]=down[p[i-1].id]+1;
			}
			if(p[n-i-1].x==p[n-i].x){
				up[p[n-i-1].id]=up[p[n-i].id ]+1;
			}
		}
		int px=p[0].x;//垂直线
		set<int>st;
		int s_min_max=0;
		for(int i=0;i<n;i++){
			int omin=maxn;
			int omax=0;
			while(i<n&&p[i].x==px){//竖直线上的所有的点
				int yid=id[p[i].id];//离散化后的点
				int BL=getsum(yid)-left[p[i].id ]-down[p[i].id ];
				int TL=i-BL-left[p[i].id ]-down[p[i].id ];
				int TR=large[p[i].id ]-TL-up[p[i].id ];
				int BR=n-1-TL-TR-BL-up[p[i].id ]-left[p[i].id ]-right[p[i].id ]-down[p[i].id ];
				add(yid,1);
				int ollie=TL+BR;
				if(omax<ollie){
					omax=ollie;
					omin=TR+BL;
				}else if(omax==ollie){
					omin=min(omin,TR+BL);
				}
				i++;
			}
			if(i<n)px=p[i--].x;
			if(omin>s_min_max){
				s_min_max=omin;
				st.clear ();
				st.insert (omax);
			}else if(omin==s_min_max){
				st.insert (omax);
			}
		}
		printf("Stan: %d; Ollie:",s_min_max);
		set<int>::iterator it;
		for(it=st.begin ();it!=st.end();it++){
			printf(" %d",*it);
		}
		printf(";\n");
	}
}

Time limit1000 ms
Memory limit65536 kB
OSLinux

题目:
Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists’ sunscreen, he wants to avoid swimming and instead reach her by jumping.
Unfortunately Fiona’s stone is out of his jump range. Therefore Freddy considers to use other stones as intermediate stops and reach her by a sequence of several small jumps.
To execute a given sequence of jumps, a frog’s jump range obviously must be at least as long as the longest jump occuring in the sequence.
The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones.

You are given the coordinates of Freddy’s stone, Fiona’s stone and all other stones in the lake. Your job is to compute the frog distance between Freddy’s and Fiona’s stone.
Input
The input will contain one or more test cases. The first line of each test case will contain the number of stones n (2<=n<=200). The next n lines each contain two integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of stone #i. Stone #1 is Freddy’s stone, stone #2 is Fiona’s stone, the other n-2 stones are unoccupied. There’s a blank line following each test case. Input is terminated by a value of zero (0) for n.
Output
For each test case, print a line saying “Scenario #x” and a line saying “Frog Distance = y” where x is replaced by the test case number (they are numbered from 1) and y is replaced by the appropriate real number, printed to three decimals. Put a blank line after each test case, even after the last one.
Sample Input
2
0 0
3 4

3
17 4
19 4
18 5

0
Sample Output
Scenario #1
Frog Distance = 5.000

Scenario #2
Frog Distance = 1.414

Prim和Kruskal都可以。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;

typedef long long ll;
const int N = 300;
const int M = 40005;
const int INF = 0x3f3f3f3f;

struct Node{
    int x, y;
    double len;
}q[M];

int fa[M];
int n, cnt;
double X[N], Y[N];
void init() {
    cnt = 0;
    for (int i = 0; i < M; i++) fa[i] = i;
    memset(X, 0, sizeof(X));
    memset(Y, 0, sizeof(Y));
}

int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

double getlen(int a, int b) {
    return sqrt((X[a] - X[b]) * (X[a] - X[b]) + (Y[a] - Y[b]) * (Y[a] - Y[b])); 
}

int cmp(Node x, Node y) {
    return x.len < y.len;
}

void input() {
    for (int i = 0; i < n; i++) {
        scanf("%lf %lf", &X[i], &Y[i]); 
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) continue;
            q[cnt].x = i;
            q[cnt].y = j;
            q[cnt++].len = getlen(i, j);
        }   
    }
}

double kruskal() {
    sort(q, q + cnt, cmp);
    double ans = 0;
    for (int i = 0; i < cnt; i++) {
        int x = find(q[i].x), y = find(q[i].y);
        if (x != y) {
            fa[x] = y;
            if (find(0) == find(1)) {
                ans = q[i].len;
                break;
            }
        }
    }
    return ans;
}

int main() {
    int Case = 1;
    while (scanf("%d", &n) != EOF, n) {
        printf("Scenario #%d\n", Case++);
        printf("Frog Distance = ");
        init(); 
        input();
        printf("%.3lf\n\n", kruskal());
    }
    return 0;
}

Time limit3000 ms
Memory limit30000 kB
OSLinux

题目:
Background
Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man who tells him whether there really is a way from the place his customer has build his giant steel crane to the place where it is needed on which all streets can carry the weight.
Fortunately he already has a plan of the city with all streets and bridges and all the allowed weights.Unfortunately he has no idea how to find the the maximum weight capacity in order to tell his customer how heavy the crane may become. But you surely know.

Problem
You are given the plan of the city, described by the streets (with weight limits) between the crossings, which are numbered from 1 to n. Your task is to find the maximum weight that can be transported from crossing 1 (Hugo’s place) to crossing n (the customer’s place). You may assume that there is at least one path. All streets can be travelled in both directions.
Input
The first line contains the number of scenarios (city plans). For each city the number n of street crossings (1 <= n <= 1000) and number m of streets are given on the first line. The following m lines contain triples of integers specifying start and end crossing of the street and the maximum allowed weight, which is positive and not larger than 1000000. There will be at most one street between each pair of crossings.
Output
The output for every scenario begins with a line containing “Scenario #i:”, where i is the number of the scenario starting at 1. Then print a single line containing the maximum allowed weight that Hugo can transport to the customer. Terminate the output for the scenario with a blank line.
Sample Input
1
3 3
1 2 3
1 3 4
2 3 5
Sample Output
Scenario #1:
4

代码:

/**
*Dijkstra + 静态邻接表 + 优先队列优化
*/

#include <iostream>
#include <deque>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXV = 1001;  //最大边数
const int INF = 0x3f3f3f3f;  //最大权值
struct Edge
{
    int to;  
    int link;  
    int w;  
    void set_val(int a, int b, int c){to = a, link = b, w = c;}
}edge[MAXV * MAXV >> 1];  //存储边
int pre[MAXV];

struct Node
{
    int v;  //顶点的标号
    int w;  //顶点v到源点的最短路
    Node(int a, int b) {v = a; w = b;}
    void set_val(int a, int b) {v = a; w = b;}
};  //设立该结构体的目的:作为优先队列的结点
int d[MAXV];  //记录最短路
bool done[MAXV];  //记录是否已找到最短路,避免重复访问
int n, m;

bool operator < (const Node& x, const Node& y)
{
    return x.w < y.w;
}

int main()
{
    int t, ca = 1;
    scanf("%d", &t);
    while(t--){
        scanf("%d %d", &n, &m);
        //建立静态邻接表
        memset(pre, -1, sizeof(pre));
        for(int i = 0; m--; ){
            int a, b, c;
            scanf("%d %d %d", &a, &b, &c);
            edge[i].set_val(a, pre[b], c);
            pre[b] = i++;
            edge[i].set_val(b, pre[a], c);
            pre[a] = i++;
        }

        //执行Dij算法,使用最小堆进行优化
        memset(done, false, sizeof(done));
        memset(d, 0, sizeof(d));  //d数组的初始化方式是关键!
        d[1] = INF;
        priority_queue<Node> que;
        que.push(Node(1, d[1]));  //源点入队
        done[1] = true;
        while(!que.empty()){
            Node cur = que.top();
            que.pop();
            for(int i = pre[cur.v]; i != -1; i = edge[i].link){
                int to = edge[i].to;
                if(!done[to] && d[to] < min(cur.w, edge[i].w)){
                    d[to] = min(cur.w, edge[i].w);
                    que.push(Node(to, d[to]));
                }
            }
        }

        //输出结果
        printf("Scenario #%d:\n%d\n\n", ca++, d[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43967023/article/details/86685395
今日推荐