ACM-ICPC 2018 北京赛区网络预赛(A B C D H)

ACM-ICPC 2018 北京赛区网络预赛(A B C D H)

自闭症患者


A. Saving Tang Monk II

题目链接
题面:

划掉

题意:

大搜索,队友写的

思路:

大搜索,队友写的

AC代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
char pic[102][102];
int dp[6][102][102];
struct step {
    int x, y, w;
    step() {}
    step(int _x, int _y, int _w) : x(_x), y(_y), w(_w) {}
};
queue<step> bfs;
int dirx[4] = { -1, 0, 1, 0 };
int diry[4] = { 0, 1, 0, -1 };
int main() {
    int x, y;
    while (scanf("%d %d", &x, &y) != EOF && x > 0 && y > 0) {
        for (int i = 0; i < x; i++) {
            scanf("%s", pic[i]);
        }
        memset(dp, 0x3f3f3f3f, sizeof(dp));
        while (!bfs.empty()) bfs.pop();
        int sx, sy, tx, ty;
        for (int i = 0; i < x; i++) {
            for (int j = 0; j < y; j++) {
                if (pic[i][j] == 'S') sx = i, sy = j;
                if (pic[i][j] == 'T') tx = i, ty = j;
            }
        }
        dp[0][sx][sy] = 0;
        bfs.push(step(sx, sy, 0));
        while (!bfs.empty()) {
            step topx = bfs.front();
            bfs.pop();
            for (int k = 0; k < 4; k++) {
                int nt = dp[topx.w][topx.x][topx.y];
                int nx = topx.x + dirx[k];
                int ny = topx.y + diry[k];
                int nw = topx.w;
                if (nx >= 0 && ny >= 0 && nx < x && ny < y) {
                    if (pic[nx][ny] == '#') {
                        if (nw == 0) continue;
                        nw--;
                        nt++;
                    } else if (pic[nx][ny] == 'B') {
                        if (nw < 5) nw++;
                    } 
                    if (pic[topx.x][topx.y] != 'P') {
                        nt++;
                    }
                    if (nt < dp[nw][nx][ny]) {
                        dp[nw][nx][ny] = nt;
                        if (pic[nx][ny] != 'T') {
                            bfs.push(step(nx, ny, nw));
                        }
                    }
                }
            }
        }
//         for (int w = 0; w <= 5; w++) {
//             for (int i = 0; i < x; i++) {
//                 for (int j = 0; j < y; j++) {
//                     printf("%d ", dp[w][i][j]);
//                 }printf("\n");
//             }printf("\n\n");
//         }
        int ans = 0x3f3f3f3f;
        for (int i = 0; i <= 5; i++) {
            ans = min(ans, dp[i][tx][ty]);
        }
        printf("%d\n", ans == 0x3f3f3f3f ? -1 : ans);
    }
    return 0;
}

B. Tomb Raider

题目链接
题面:

划掉

题意:

寻址n个串的最长公共子序列。

思路:

拿一个最短串枚举所有子序列,在其他串中查找。暴力

AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <cmath>
#include <map>

using namespace std;

typedef long long LL;

const int MAXN = 1000005;

string s[12];
int use[10];
string ans;

int main()
{
    int n;
    string temp;
    string now;
    while(cin >> n){
        for(int i = 0; i < n; ++i){
            cin >> s[i];

        }
        for(int i = 1; i < n; ++i){
            s[i] += s[i];
            //cout << s[i] << endl;
        }
        int len = s[0].length();
        int maxx = (1<<len);
        ans = "";
        for(int i = 0; i < maxx; ++i){
            temp = "";
            int cnt = 0;
            for(int j = 0; j < len; ++j){
                if(i&(1<<j)){
                    temp += s[0][j];
                }
            }
            int tl = temp.length();
            for(int x = 0; x < tl; ++x){
                now = temp.substr(x+1, tl-(x+1)) + temp.substr(0, x);
                now.push_back(temp[x]);
                int nl = now.length();
                //cout << now << endl;
                bool flag = true;
                bool tempflag;
                for(int j = 1; j < n; ++j){
                    int lj = s[j].length()/2;
                    tempflag = false;
                    for(int st = 0; st < lj; ++st){
                        if(s[j][st] != now[0]) continue;
                        int cur = 1;
                        if(nl == 1){
                            tempflag = true;
                            break;
                        }
                        for(int k = st+1; k < st+lj; ++k){
                            if(s[j][k] == now[cur]){
                                ++cur;
                                if(cur == nl){
                                    tempflag = true;
                                    break;
                                }
                            }
                        }
                        if(tempflag) break;
                    }
                    if(!tempflag){
                        flag = false;
                        break;
                    }
                }
                if(flag){
                    //cout << now << endl;
                    if(now.length() > ans.length()){
                        ans = now;
                        reverse(now.begin(), now.end());
                        if(now < ans){
                            ans = now;
                        }
                    }else if(now.length() == ans.length()){
                        if(now < ans){
                            ans = now;
                        }
                        reverse(now.begin(), now.end());
                        if(now < ans){
                            ans = now;
                        }
                    }
                }
            }
        }
        if(ans == ""){
            cout << 0 << endl;
        }else{
            cout << ans << endl;
        }
    }
}

C. Cheat

题目链接
题面:

划掉

题意:

斗地主。

思路:

大模拟,队友写的。

AC代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int dictOrder[] = {9, 1, 2, 3, 4, 5, 6, 7, 8, 0, 10, 12, 11};
int cards[4][13];
int fuck[4][13];
int tables[13];
char fv[5];
int rankNow = 0, rounderRank = -1, rounderCnt = -1, roundext = -1, roundNow = 0;
int getcard(char* sp) {
#define card(a, b) if (strcmp(sp, a) == 0) return b;
    card("A", 0); card("2", 1); card("3", 2); card("4", 3); card("5", 4); card("6", 5);
    card("7", 6); card("8", 7); card("9", 8); card("10", 9); card("J", 10); card("Q", 11);
    card("K", 12);
    return -1;
#undef card
}
const char* getcardII(int sp) {
#define card(b, a) if (sp == a) return b;
    card("A", 0); card("2", 1); card("3", 2); card("4", 3); card("5", 4); card("6", 5);
    card("7", 6); card("8", 7); card("9", 8); card("10", 9); card("J", 10); card("Q", 11);
    card("K", 12);
    return "?";
#undef card
}
int findSmallest(int p) {
    for (int i = 0; i < 13; i++) {
        if (cards[p][dictOrder[i]] > 0) {
            return dictOrder[i];
        }
    }
    return -1;
}
int findNextCard(int p) {
    for (int i = 0; i < 13; i++) {
        if (fuck[p][i] > 0) {
            fuck[p][i]--;
            return i;
        }
    }
    return -1;
}
void putOneDictSmallest(int p) {
    int ck = findSmallest(p);
    if (ck >= 0) {
        cards[p][ck]--;
        rounderCnt = 1;
        rounderRank = ck;
        tables[ck]++;
    }
}
void putSomeTrueCard(int p, int cnt) {
    rounderCnt = cnt;
    cards[p][rankNow] -= cnt;
    rounderRank = rankNow;
    tables[rankNow] += cnt;
}
bool action(int p, bool realDo, int rankx) {
    if (realDo) roundext = -1;
    if (p == 0) {
        if (cards[p][rankx] > 0) {
            if (realDo) putSomeTrueCard(p, 1);
            return true;
        } else {
            if (realDo) putOneDictSmallest(p);
            return false;
        }
    } else if (p == 1) {
        if (cards[p][rankx] > 0) {
            if (realDo) putSomeTrueCard(p, cards[p][rankx]);
            return true;
        } else {
            if (realDo) putOneDictSmallest(p);
            return false;
        }
    } else if (p == 2) {
        if (cards[p][rankx] > 0) {
            if (realDo) putSomeTrueCard(p, cards[p][rankx]);
            return true;
        } else {
            if (realDo) {
                int nums = 9999, idx = -1;
                for (int i = 0; i < 13; i++) {
                    if (cards[p][dictOrder[i]] > 0) {
                        if (cards[p][dictOrder[i]] < nums) {
                            nums = cards[p][dictOrder[i]];
                            idx = dictOrder[i];
                        }
                    }
                }
                rounderCnt = cards[p][idx];
                cards[p][idx] = 0;
                rounderRank = idx;
                tables[idx] += rounderCnt;
            }
            return false;
        }
    } else if (p == 3) {
        if (cards[p][rankx] > 2) {
            if (realDo) putSomeTrueCard(p, cards[p][rankx]);
            return true;
        } else {
            if (realDo) {
                putSomeTrueCard(p, cards[p][rankx]);
                roundext = findSmallest(p);
                if (roundext >= 0) {
                    cards[p][roundext]--;
                    tables[roundext]++;
                }
                return roundext == -1;
            }
            return false;
        }
    }
}
bool shouldFuck(int p) {
    if (p == 0) {
        if ((roundNow + 1) % 4 == p && !action(p, false, (rankNow + 1) % 13)) {
            return true;
        } else {
            return cards[p][rankNow] + (rounderCnt + (roundext >= 0)) > 4;
        }
    } else if (p == 1) {
        return (roundNow + 1) % 4 == p && !action(p, false, (rankNow + 1) % 13);
    } else if (p == 2) {
        return cards[p][rankNow] == 4;
    } else if (p == 3) {
        return findSmallest(roundNow % 4) == -1;
    }
}
void getAllCards(int p) {
    for (int i = 0; i < 13; i++) {
        cards[p][i] += tables[i];
        tables[i] = 0;
    }
}
void printCards() {
    memcpy(fuck, cards, sizeof(cards));
    for (int i = 0; i < 4; i++) {
        for (int k = 0; k < 998; k++) {
            int next = findNextCard(i);
            if (next == -1) {
                if (k == 0) printf("WINNER");
                printf("\n");
                break;
            }
            else {
                if (k > 0) printf(" ");
                printf("%s", getcardII(next));
            }
        }
    }
}
int main() {
    bool gaming = true;
    while (gaming) {
        memset(cards, 0, sizeof(cards));
        memset(tables, 0, sizeof(tables));
        for (int i = 0, j = -1; i < 52; i++) {
            if (i % 13 == 0) j++;
            if (scanf("%s", fv) == EOF) {
                gaming = false;
                break;
            }
            int cc = getcard(fv);
            if (cc >= 0) cards[j][cc]++;
        }
        rankNow = 0, roundNow = 0, rounderRank = -1, rounderCnt = -1, roundext = -1;
        if (gaming) {
            while (true) {
                //printf("round: %s\n", getcardII(rankNow));
                bool really = action(roundNow % 4, true, rankNow);
                //printCards();
                //printf("rankcnt %d ext: %s\n", rounderCnt, getcardII(roundext));
                //printf("p%d is really: %d\n", roundNow % 4, really);
                for (int j = roundNow + 1; j < roundNow + 4; j++) {
                    if (shouldFuck(j % 4)) {
                        //printf("p%d do fuck!\n", j % 4);
                        if (!really) {
                            getAllCards(roundNow % 4);
                        } else {
                            getAllCards(j % 4);
                        }
                        break;
                    }
                }
                rankNow = (rankNow + 1) % 13;
                if (findSmallest(roundNow % 4) == -1) break;
                roundNow++;
            }
            printCards();
        }
    }
    return 0;
}

D. 80Days

题目链接
题面:

划掉

题意:

n个成环的城市,到达第i个城市获得 a i a_i ai,离开丢掉 b i b_i bi,初始有c,全程拥有值不能为负数,问是否可行,可行就输出最小的出发点。

思路:

尺取法,维护一个连续段的区间以及C+在该区间旅游费用和,左端点不变,右端点向右移,如果遇到无法进行的情况则移动左端点。

AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <cmath>
#include <map>

using namespace std;

typedef long long LL;

const int MAXN = 1000005;

LL a[2*MAXN];
LL b[2*MAXN];

int main()
{
    int t;
    cin >> t;
    int n;
    LL c;
    while(t--){
        scanf("%d%lld", &n, &c);
        for(int i = 1; i <= n; ++i){
            scanf("%lld", &a[i]);
            a[n+i] = a[i];
        }
        for(int i = 1; i <= n; ++i){
            scanf("%lld", &b[i]);
            b[n+i] = b[i];
        }
        int l = 1, r = 1;
        LL now = c + a[1];
        bool flag = false;
        while(true){
            now -= b[r];
            while(now < 0 && l < r){
                now -= a[l];
                now += b[l];
                l++;
            }
            if(l == r && now < 0){
                l++;
                r++;
                now = c + a[l];
                continue;
            }
            r++;
            if(r-l == n){
                flag = true;
                break;
            }
            now += a[r];
            while(now < 0 && l < r){
                now -= a[l];
                now += b[l];
                l++;
            }
            if(l > n){
                flag = false;
                break;
            }
        }
        if(flag){
            printf("%d\n", l);
        }else{
            printf("-1\n");
        }
    }
}

H. K-Demensional Foil II

题目链接
题面:

划掉

题意:

K维空间,给定一个曼哈顿距离意义下的球,N个点,求这些点到该球上在欧几里得距离下最小的点。

思路:

直接考虑对欧几里得距离进行缩小,那么可以写成一个类似于方差形式的表达式,那么要使得该表达式最小,令这K维当中对表达式值贡献最大的值减小。
问题变形为满足哈密顿距离小于R时放缩该表达式使得其值最小,二分即可。

AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X  first
#define Y  second
#define REP(i,st,ed)    for(int i=st;i<=ed;++i)
#define IREP(i,st,ed)   for(int i=ed;i>=st;--i)
#define TCASE(T)    cin>>T;while(T--)


const int MAXN = 105;
const int MOD = 2333333 ;
const int INF = 1e9+7;

int _;

using namespace std;

const double EPS = 1e-6;

double foil[MAXN];
double spcf[MAXN];
double go[MAXN];
bool mk[MAXN];
int N, K;
double R;

int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w+",stdin);
    TCASE(_)
    {
        scanf("%d%d",&N,&K);
        scanf("%lf",&R);
        REP(i,1,K)  scanf("%lf",&foil[i]);
        REP(t,1,N)
        {
            REP(i,1,K)
            {
                scanf("%lf",&spcf[i]);
                go[i] = fabs(spcf[i]-foil[i]);
                mk[i] = (spcf[i]>=foil[i]);
            }
            double minn = 0;
            double maxn = 1e8;
            double mid, tmp;
            while(minn+EPS<=maxn)
            {
                mid = (minn+maxn)/2.0;
                tmp = 0;
                REP(kk,1,K) tmp+=max(0.0,go[kk]-mid);
                if(tmp<=R)  maxn = mid-EPS;
                else    minn = mid+EPS;
            }
            REP(i,1,K)
            {
                if(go[i]>=maxn)    go[i]=maxn;
                if(mk[i])   tmp = spcf[i]-go[i];
                else    tmp = spcf[i]+go[i];
                printf("%.5f ",tmp);
            }
            printf("\n");
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值