The 2018 ACM-ICPC Asia Beijing First Round Online Contest

The 2018 ACM-ICPC Asia Beijing First Round Online Contest 

A - Saving Tang Monk II

题意:

给出一个地图

S起点 T终点 #毒气 B氧气 P药片 .空地

每次可以向上下左右4个方向移动,花费时间为1

#毒气室,需要一个氧气瓶,并且需要额外花费时间1休息

B氧气室,有无数个氧气瓶,每进入一次可获得一个氧气瓶

P加速药片,下次移动不花费时间

最多只能带5个氧气瓶

题解:

宽搜,维护到(x,y)位置带z个氧气的最小时间

#include <bits/stdc++.h>
#define FOR(I,S,T) for(int I=(S);I<=(T);I++)
//#define mp make_pair
#define pb push_back
#define eb emplace_back
#define endl '\n'
using namespace std;
typedef long long ll;
const int maxn = 1e2 + 2;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
int dis[maxn][maxn][10];
char mp[maxn][maxn];

struct node{
    int x, y, o, dis;
    node(){x = y = o = dis = 0;}
    node(int a, int b, int c, int d){
        x = a; y = b; o= c; dis = d;
    }
};
int sx, sy, ex, ey, Ans;
queue<node> que;
int dir[4][2] = {{1,0},{-1,0},{0,-1},{0,1}};
int n , m;

int main() {
    while (~scanf("%d%d", &n, &m)){
        if (n == 0 && m == 0) break;
        getchar();
        memset(dis, inf, sizeof(dis));
        while (que.size()) que.pop();
        FOR(i,0,n-1) {
            FOR(j,0,m-1) {
                mp[i][j] = getchar();
                if (mp[i][j] == 'S') sx = i, sy = j;
                else if (mp[i][j] == 'T') ex = i, ey = j;
            }
            getchar();
        }
        dis[sx][sy][0] = 0;
        que.push(node(sx,sy,0,0));
        while (que.size()){
            node u = que.front();
            int x = u.x, y = u.y;
            que.pop();
            FOR(i,0,3){
                int nx = u.x + dir[i][0], ny = u.y + dir[i][1];
                if (nx < 0 || nx >= n) continue;
                if (ny < 0 || ny >= m) continue;
                if (mp[x][y] == '.' || mp[x][y] == 'S'){
                    FOR(j,0,5){
                        if (dis[x][y][j] + 1 < dis[nx][ny][j]){
                            dis[nx][ny][j] = dis[x][y][j] + 1;
                            que.push(node(nx,ny,j,dis[nx][ny][j]));
                        }
                    }
                }
                else if (mp[x][y] == '#'){
                    FOR(j,0,4){
                        if (dis[x][y][j+1] + 2 < dis[nx][ny][j]){
                            dis[nx][ny][j] = dis[x][y][j+1] + 2;
                            que.push(node(nx, ny, j, dis[nx][ny][j]));
                        }
                    }
                }
                else if (mp[x][y] == 'B'){
                    FOR(j,1,5){
                        if (dis[x][y][j-1] + 1 < dis[nx][ny][j]){
                            dis[nx][ny][j] = dis[x][y][j-1] + 1;
                            que.push(node(nx,ny,j,dis[nx][ny][j]));
                        }
                    }
                }
                else if (mp[x][y] == 'P'){
                    FOR(j,0,5){
                        if (dis[x][y][j] < dis[nx][ny][j]){
                            dis[nx][ny][j] = dis[x][y][j];
                            que.push(node(nx,ny,j,dis[nx][ny][j]));
                        }
                    }
                }
            }
            Ans = inf;
        }
        FOR(i,0,5){
            if (dis[ex][ey][i] < Ans){
                Ans = dis[ex][ey][i];
            }
        }
        if (Ans == inf)  printf("-1\n");
        else printf("%d\n", Ans) ;
    }
    return 0;
}

B - Tomb Raider

题意:

给n个串,求这n个串的最长公共子串

题解: 二进制分解

分解出一个串的所有子串,然后枚举第一串的子串,暴力判断在其他串中是否出现过

#include <bits/stdc++.h>
#define FOR(I,S,T) for(int I=(S);I<=(T);I++)
#define pb push_back
#define mp male_pair
#define fi first
#define se second
#define endl '\n'
using namespace std;
set<string> s[20];
vector <string> ans;

int n;

int main() {
    while(~scanf("%d", &n)){
        string st;
        ans.clear();
        FOR(i,0,n)s[i].clear();
        FOR(t,0,n-1){
            cin >> st;
            string tmp = "";
            int len = st.size();
            FOR(i,1,(1<<len)-1){
                int x = i;
                tmp = "";
                FOR(j,0,len-1){
                    if (x & (1<<j)){
                       tmp.insert(tmp.end(), 1,st[j]);
                    }
                }
                string tmp2 = "";
                FOR(j,1,tmp.size()-1){
                    tmp2 = tmp.substr(j);
                    string tmp3 = tmp.substr(0,j);
                    tmp2.insert(tmp2.end(), tmp3.begin(), tmp3.end());
                    s[t].insert(tmp2);
                }
                s[t].insert(tmp);
            }
        }
        for (auto i : s[0]){
            int flag = 1;
            FOR(j,1,n-1){
                if (s[j].count(i) == 0){
                    flag = 0;
                    break;
                }
            }
            if (flag) ans.pb(i);
        }
        sort(ans.begin(), ans.end());
        string Ans = "";
        for (auto i : ans){
            if(i.size() > Ans.size()) Ans = i;
        }
        if (Ans == "") cout << "0" << endl;
        else cout << Ans << endl;
    }
    return 0;
}

 

C - Cheat

题意:给出”吹牛皮“的打牌规则和4个人的出牌策略

题解:

大模拟,按照题解写就行

学弟写的代码;

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int poke[5][14];
int hand[5];
int table[14];
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0), cout.tie(0);
	char ch;
	while (cin >> ch)
	{
		memset(poke, 0, sizeof(poke));
		memset(table, 0, sizeof(table));
		if (ch == 'A')
			poke[1][1]++;
		else if ('2' <= ch && ch <= '9')
			poke[1][ch - '0']++;
		else if (ch == '1')
		{
			cin >> ch;
			poke[1][10]++;
		}
		else if (ch == 'J')
			poke[1][11]++;
		else if (ch == 'Q')
			poke[1][12]++;
		else if (ch == 'K')
			poke[1][13]++;
		for (int i = 1; i <= 4; i++)
			for (int j = 1; j <= 13; j++)
			{
				if (i == 1 && j == 1)
					continue;
				cin >> ch;
				if (ch == 'A')
					poke[i][1]++;
				else if ('2' <= ch && ch <= '9')
					poke[i][ch - '0']++;
				else if (ch == '1')
				{
					cin >> ch;
					poke[i][10]++;
				}
				else if (ch == 'J')
					poke[i][11]++;
				else if (ch == 'Q')
					poke[i][12]++;
				else if (ch == 'K')
					poke[i][13]++;
			}
		hand[1] = hand[2] = hand[3] = hand[4] = 13;
		int rndpoke = 0;
		int rndplayer = 0;
		while (hand[1] && hand[2] && hand[3] && hand[4])
		{
			rndpoke++;
			rndpoke = (rndpoke - 1) % 13 + 1;
			rndplayer++;
			rndplayer = (rndplayer - 1) % 4 + 1;
			if (rndplayer == 1)
			{
				if (poke[1][rndpoke])
				{
					poke[1][rndpoke]--;
					hand[1]--;
					table[rndpoke]++;
					
					int nextrndpoke = rndpoke + 1;
					nextrndpoke = (nextrndpoke - 1) % 13 + 1;

					if (poke[2][nextrndpoke] == 0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[2][i] += table[i];
							hand[2] += table[i];
							table[i] = 0;
						}
					}
					else if (poke[3][rndpoke] == 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[3][i] += table[i];
							hand[3] += table[i];
							table[i] = 0;
						}
					}
					else if (hand[1] == 0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[4][i] += table[i];
							hand[4] += table[i];
							table[i] = 0;
						}
					}
				}
				else
				{
					int curpoke = -1;
					if (poke[1][10])
						curpoke = 10;
					if (curpoke == -1)
					{
						for(int i=2;i<=9;i++)
							if (poke[1][i])
							{
								curpoke = i;
								break;
							}
					}
					if (curpoke == -1)
					{
						if (poke[1][1])
							curpoke = 1;
						else if (poke[1][11])
							curpoke = 11;
						else if (poke[1][13])
							curpoke = 13;
						else
							curpoke = 12;
					}
					poke[1][curpoke]--;
					hand[1]--;
					table[curpoke]++;

					int nextrndpoke = rndpoke + 1;
					nextrndpoke = (nextrndpoke - 1) % 13 + 1;

					if (poke[2][nextrndpoke] == 0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[1][i] += table[i];
							hand[1] += table[i];
							table[i] = 0;
						}
					}
					else if (poke[3][rndpoke] == 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[1][i] += table[i];
							hand[1] += table[i];
							table[i] = 0;
						}
					}
					else if (hand[1] == 0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[1][i] += table[i];
							hand[1] += table[i];
							table[i] = 0;
						}
					}
				}
			}
			else if(rndplayer==2)
			{
				if (poke[2][rndpoke])
				{
					int num = poke[2][rndpoke];
					hand[2] -= num;
					poke[2][rndpoke] = 0;
					table[rndpoke] += num;

					if (poke[3][rndpoke] == 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[3][i] += table[i];
							hand[3] += table[i];
							table[i] = 0;
						}
					}
					else if (hand[2] == 0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[4][i] += table[i];
							hand[4] += table[i];
							table[i] = 0;
						}
					}
					else if (num + poke[1][rndpoke] > 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[1][i] += table[i];
							hand[1] += table[i];
							table[i] = 0;
						}
					}
				}
				else
				{
					int curpoke = -1;
					if (poke[2][10])
						curpoke = 10;
					if (curpoke == -1)
					{
						for (int i = 2; i <= 9; i++)
							if (poke[2][i])
							{
								curpoke = i;
								break;
							}
					}
					if (curpoke == -1)
					{
						if (poke[2][1])
							curpoke = 1;
						else if (poke[2][11])
							curpoke = 11;
						else if (poke[2][13])
							curpoke = 13;
						else
							curpoke = 12;
					}
					poke[2][curpoke]--;
					hand[2]--;
					table[curpoke]++;

					if (poke[3][rndpoke] == 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[2][i] += table[i];
							hand[2] += table[i];
							table[i] = 0;
						}
					}
					else if(hand[2]==0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[2][i] += table[i];
							hand[2] += table[i];
							table[i] = 0;
						}
					}
					else if (1 + poke[1][rndpoke] > 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[2][i] += table[i];
							hand[2] += table[i];
							table[i] = 0;
						}
					}
				}
			}
			else if (rndplayer == 3)
			{
				if (poke[3][rndpoke])
				{
					int num = poke[3][rndpoke];
					hand[3] -= num;
					poke[3][rndpoke] = 0;
					table[rndpoke] += num;

					if (hand[3] == 0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[4][i] += table[i];
							hand[4] += table[i];
							table[i] = 0;
						}
					}
					else if (num + poke[1][rndpoke] > 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[1][i] += table[i];
							hand[1] += table[i];
							table[i] = 0;
						}
					}
				}
				else
				{
					int minnum = 4;
					for (int i = 1; i <= 13; i++)
						if (poke[3][i])
							minnum = min(minnum, poke[3][i]);
					int curpoke = -1;
					if (poke[3][10] == minnum)
						curpoke = 10;
					if(curpoke==-1)
						for(int i=2;i<=9;i++)
							if (poke[3][i] == minnum)
							{
								curpoke = i;
								break;
							}
					if (curpoke == -1)
						if (poke[3][1] == minnum)
							curpoke = 1;
						else if (poke[3][11] == minnum)
							curpoke = 11;
						else if (poke[3][13] == minnum)
							curpoke = 13;
						else
							curpoke = 12;

					hand[3] -= minnum;
					poke[3][curpoke] = 0;
					table[curpoke] += minnum;

					if (hand[3] == 0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[3][i] += table[i];
							hand[3] += table[i];
							table[i] = 0;
						}
					}
					else if (minnum + poke[1][rndpoke] > 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[3][i] += table[i];
							hand[3] += table[i];
							table[i] = 0;
						}
					}
				}
			}
			else if (rndplayer == 4)
			{
				if (poke[4][rndpoke] == 3 || poke[4][rndpoke] == 4)
				{
					int num = poke[4][rndpoke];
					hand[4] -= num;
					poke[4][rndpoke] = 0;
					table[rndpoke] += num;

					int nextrndpoke = rndpoke + 1;
					nextrndpoke = (nextrndpoke - 1) % 13 + 1;

					if (num + poke[1][rndpoke] > 4 || poke[1][nextrndpoke] == 0)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[1][i] += table[i];
							hand[1] += table[i];
							table[i] = 0;
						}
					}
					else if (poke[3][rndpoke] == 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[3][i] += table[i];
							hand[3] += table[i];
							table[i] = 0;
						}
					}
				}
				else
				{
					int num1 = poke[4][rndpoke];
					hand[4] -= num1;
					poke[4][rndpoke] = 0;
					table[rndpoke] += num1;
					int num2=0;
					if (hand[4])
						num2 = 1;
					int curpoke = -1;
					if (poke[4][10])
						curpoke = 10;
					if (curpoke == -1)
					{
						for (int i = 2; i <= 9; i++)
							if (poke[4][i])
							{
								curpoke = i;
								break;
							}
					}
					if (curpoke == -1)
						if (poke[4][1])
							curpoke = 1;
						else if (poke[4][11])
							curpoke = 11;
						else if (poke[4][13])
							curpoke = 13;
						else
							curpoke = 12;
					if (num2)
					{
						poke[4][curpoke] -= num2;
						table[curpoke] += num2;
						hand[4] -= num2;
					}

					int nextrndpoke = rndpoke + 1;
					nextrndpoke = (nextrndpoke - 1) % 13 + 1;

					if (num1 + num2 + poke[1][rndpoke] > 4 || poke[1][nextrndpoke] == 0)
					{
						if(num2)
						for (int i = 1; i <= 13; i++)
						{
							poke[4][i] += table[i];
							hand[4] += table[i];
							table[i] = 0;
						}
						else
							for (int i = 1; i <= 13; i++)
							{
								poke[1][i] += table[i];
								hand[1] += table[i];
								table[i] = 0;
							}
					}
					else if (poke[3][rndpoke] == 4)
					{
						for (int i = 1; i <= 13; i++)
						{
							poke[4][i] += table[i];
							hand[4] += table[i];
							table[i] = 0;
						}
					}
				}
			}
		}
		for (int i = 1; i <= 4; i++)
		{
			if (hand[i] == 0)
				cout << "WINNER" << endl;
			else
			{
				for (int j = 1; j <= 13; j++)
				{
					while (poke[i][j])
					{
						if (j == 1)
							cout << "A";
						else if (2 <= j && j <= 10)
							cout << j;
						else if (j == 11)
							cout << "J";
						else if (j == 12)
							cout << "Q";
						else if (j == 13)
							cout << "K";
						poke[i][j]--;
						hand[i]--;
						if (hand[i] == 0)
							cout << endl;
						else
							cout << " ";
					}
				}
			}
		}
	}
	return 0;
}

D - 80 Days

题意:

初始有c个钱,按照一个环遍历n个城市,到达每个城市可以获得a元,离开时花费b元,问从哪个城市出发,能遍历n个城市

题解:

尺取,假设从1号城市出发,先后向遍历到不能遍历的城市,再将出发城市向后移,知道又能遍历新的城市,如此循环

#include<bits/stdc++.h>
#define FOR(I,S,T) for(int I=(S);I<=(T);I++)
#define pb push_back
#define mp make_pair
#define eb emplace_back

using namespace std;
typedef long long ll;
const int maxn = 1e6 + 2;
int l, r;
int n, k;
ll sum;
int a[maxn];
int main() {
    int T;
    cin >> T;
    while (T--){
        sum = 0;
        scanf("%d%d", &n, &k);
        FOR(i,1,n) scanf("%d", &a[i]);
        FOR(i,1,n) {
            int x; scanf("%d", &x);
            a[i] -= x;
        }
        FOR(i,1,n) a[i+n] = a[i];
        l = 1, r =1;
        sum += a[1];
        while (r < 2 * n){
            sum += a[++r];
            while (l <= r && sum < -k) sum-=a[l],l++;
            //cout << sum << " " << l <<" " << r << endl;
            if (r - l + 1>= n) break;
        }
        if (l == 0) l++;
        if (r - l + 1>= n) printf("%d\n", l);
        else printf("-1\n");

    }
    return 0;
}

G - The Mole

题意:平面上n个线段,给一个点,问到最近的线段的矩阵的距离,数据随机

题解:分块暴力

 先将平面分块,然后再暴力计算周围的9个方块,如果没有,就暴力所有的线段

这种解法有问题,有返例,但是有个学弟这个写过了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>

using namespace std;

const int N=1e4+5;
const int M=256;
const double eps=1e-8;

vector<int> v[M+1][M+1];

struct Point{
    double x,y;

    Point(double _x=0,double _y=0):x(_x),y(_y){}

    void in()
    {
        scanf("%lf%lf",&x,&y);
    }

    Point operator -(const Point &b)const {
        return Point(x-b.x,y-b.y);
    }
    Point operator +(const Point &b)const {
        return Point(x+b.x,y+b.y);
    }
    bool operator ==(const Point &b)const {
        return x==b.x&&y==b.y;
    }
    double operator ^(const Point &b)const {
        return x*b.y-y*b.x;
    }
    double operator *(const Point &b)const {
        return x*b.x+y*b.y;
    }
    double distance(Point p){
        return hypot(x-p.x,y-p.y);
    }
    void getid(int &a,int &b){
        a=x/M,b=y/M;
    }
};
struct Line{
    Point s,e;

    void in(){
        s.in();
        e.in();
    }
    void setid(int id){
        int a,b,aflag,bflag;
        Point tem=e-s;

        for(int i=0;i<=M;i++)
        {
            Point p=s+Point(tem.x*i/M,tem.y*i/M);
            p.getid(a,b);

            if(a==aflag&&b==bflag)
                continue;

            v[a][b].push_back(id);
            aflag=a,bflag=b;
        }
    }
    double dispointtoseg(Point p){
        if(s==e)
            return p.distance(s);
        if((p-s)*(e-s)<-eps)
            return p.distance(s);
        if((p-e)*(s-e)<-eps)
            return p.distance(e);
        return fabs((s-p)^(e-p))/s.distance(e);
    }
};

int vis[N]={-1};
Line l[N];

int main()
{
    int n,m;

    scanf("%d%d",&n,&m);

    for(int i=0;i<n;i++)
    {
        l[i].in();
        l[i].setid(i);
    }

    while(m--)
    {
        Point p;
        p.in();

        int ans=1,xblock,yblock;
        double tem=1e50;
        p.getid(xblock,yblock);

        for(int i=xblock-1;i<=xblock+1;i++)
            for(int j=yblock-1;j<=yblock+1;j++)
            {
                if(i<0)
                    break;
                if(j<0)
                    continue;

                for(int k=0;k<(int)v[i][j].size();k++)
                {
                    if(vis[v[i][j][k]]==m)
                        continue;

                    vis[v[i][j][k]]=m;
                    double dis=l[v[i][j][k]].dispointtoseg(p);
                    if(dis+eps<tem)
                        tem=dis,ans=v[i][j][k]+1;
                    else if(fabs(dis-tem)<eps)
                        ans=min(ans,v[i][j][k]+1);
                }
            }

        if(tem==1e50)
            for(int i=0;i<n;i++)
            {
                double dis=l[i].dispointtoseg(p);
                if(dis+eps<tem)
                    tem=dis,ans=i+1;
                else if(fabs(dis-tem)<eps)
                    ans=min(ans,i+1);
            }

        printf("%d\n",ans);
    }

    return 0;
}

H - K-Dimensional Foil II

题意:平面上某一点到,求K维菱形的最短距离

题解:几何数学

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100+2;
int c[maxn], a2[maxn], a[maxn], s[maxn];
int r;
double ans[maxn];
void solve(int k){
	double dif = 0.0,num = 0.0;
	for (int i = 0; i < k; i++){
	    num += a[i]*s[i];
	    dif += a[i]*a[i];
	}
	num -= r;
	double t = num / dif;
	bool flag=1;
	for (int i = 0; i < k; i++){
	    ans[i] = s[i] - a[i] * t;
	    if (ans[i] < 0) s[i] = a[i] = ans[i] = 0, flag=0;
	} 
	if (!flag) solve(k);
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n,K;
        scanf("%d%d", &n, &K);
        scanf("%d",&r);
        for (int i = 0; i < K; i++)
            scanf("%d", &c[i]);
        for (int t = 0; t < n; t++){
            memset(ans, 0, sizeof(ans));
            for (int i = 0; i < K; i++){
                scanf("%d",&s[i]);
                s[i] -= c[i];
                a2[i] = s[i] > 0 ? 1 : -1;
                if (s[i]==0) a2[i] = 0;
                a[i] = (a2[i] != 0);
                s[i] = abs(s[i]);
            }
            solve(K);
            for (int i = 0; i < K; i++){
                printf("%.8f",ans[i]*a2[i]+c[i]);
                if (i!= K-1) putchar(' ');
                else putchar('\n');
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值