gdut校赛决赛题解

比较水的比赛,水下博客贴个题解。

Problem A: Krito的讨伐
直接模拟,把可见范围内的怪物都扔进优先队列,先杀防御低的,最后判断还有没有怪剩余就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef struct Mon
{
    int def;
    int add;
    int r;
    bool operator <(const Mon &r)const
    {
        return r.def<def;
    }
} Mon;

typedef struct
{
    int num;
    vector<Mon>M;
} room;

priority_queue<Mon>que;
int t;
int n,m;
long long int atk;
bool dis[1005][1005];
room R[1005];
bool vis[1005];
bool flag=0;
void add(int num)
{
    vis[num]=1;
    if(R[num].num==0)
    {
        for(int i=0;i<n;i++)
        {
            if(dis[num][i] && vis[i]==0)
                add(i);
        }
    }
    else
    {
        for(int i=0;i<R[num].num;i++)
            que.push(R[num].M[i]);
    }
}
bool solve()
{
    Mon tmp;
    add(0);
    while(!que.empty())
    {
        tmp=que.top();
        if(atk<tmp.def)
        {
            break;
        }
        que.pop();
        atk+=tmp.add;
        R[tmp.r].num--;
        if(R[tmp.r].num==0)
        {
            for(int i=0;i<n;i++)
            {
                if(dis[tmp.r][i] && vis[i]==0)
                {
                    add(i);
                }
            }
        }
    }
    long long int left=0;
    for(int i=0; i<n; i++)
    {
        left+=R[i].num;
    }
    if(left>0)
        return 0;
    return 1;
}

int main()
{
    cin >> t;
    int a,b,c;
    Mon tmp;
    while(t--)
    {
        cin >> n >> m;
        while(!que.empty())que.pop();
        memset(dis,0,sizeof(dis));
        memset(R,0,sizeof(R));
        memset(vis,0,sizeof(vis));
        for(int i=0; i<n-1; i++)
        {
            scanf("%d%d",&a,&b);
            dis[a][b]=dis[b][a]=1;
        }
        cin >> atk;
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            R[a].num++;
            tmp.def=b,tmp.add=c;
            tmp.r=a;
            R[a].M.push_back(tmp);
        }
        if(solve())
            cout << "Oh yes." << endl;
        else
            cout << "Good Good Study,Day Day Up." << endl;
    }
    return 0;
}

Problem B: Sward Art Online
我直接写了几个DP,貌似有菊苣枚举+DP,都是可以的。

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
long long int t,m,a,b,c,d;
long long int dp1[100005],dp2[100005],dp3[100005],dp4[100005];
long long int num[100005];
typedef struct
{
    int atk,cost;
}node;
typedef struct
{
    long long int atk,cost,num,buff;
}newnode;
node tou[100005];
newnode shou[100005];
node wuqi[100005];
node wuqi2[100005];
int main()
{
    //freopen("input.txt","r",stdin);
    cin >> t;
    node temp;
    newnode temp1;
    long long int tmp,tmpa,tmpb,tmpc;
    while(t--)
    {
        memset(num,-1,sizeof(num));
        cin >> m >> a >> b >> c >> d;
        for(long long int i=0;i<a;i++)
        {
            scanf("%lld%lld",&tmp,&tmpa);
            temp.cost=tmp;
            temp.atk=tmpa;
            tou[i]=temp;
        }
        for(long long int i=0;i<b;i++)
        {
            scanf("%lld%lld%lld%lld",&tmp,&tmpa,&tmpb,&tmpc);
            temp1.cost=tmp,temp1.atk=tmpa,temp1.num=tmpb,temp1.buff=tmpc;
            shou[i]=temp1;
        }
        for(long long int i=0;i<c;i++)
        {
            scanf("%lld%lld",&tmp,&tmpa);
            temp.cost=tmp;
            temp.atk=tmpa;
            wuqi[i]=temp;
        }
        for(long long int i=0;i<d;i++)
        {
            scanf("%lld%lld",&tmp,&tmpa);
            temp.cost=tmp;
            temp.atk=tmpa;
            wuqi2[i]=temp;
        }

        for(long long int i=0;i<a;i++)
        {
            temp=tou[i];
            if(m-temp.cost<0)
                continue;
            if(dp1[m-temp.cost]<temp.atk)
            {
                dp1[m-temp.cost]=temp.atk;
                num[m-temp.cost]=i;
            }
        }
        memcpy(dp2,dp1,sizeof(dp1));
        for(long long int i=0;i<b;i++)
        {
            temp1=shou[i];
            for(long long int j=temp1.cost;j<=m;j++)
            {
                if(temp1.num!=-1 && temp1.num==num[j])
                {
                    if(dp2[j-temp1.cost]<dp1[j]+temp1.buff+temp1.atk)
                    {
                        dp2[j-temp1.cost]=dp1[j]+temp1.buff+temp1.atk;
                    }
                }
                else
                {
                    if(dp2[j-temp1.cost]<dp1[j]+temp1.atk)
                        dp2[j-temp1.cost]=dp1[j]+temp1.atk;
                }
            }
        }
        memcpy(dp3,dp2,sizeof(dp2));
        memset(num,-1,sizeof(num));
        for(long long int i=0;i<c;i++)
        {
            temp=wuqi[i];
            for(long long int j=temp.cost;j<=m;j++)
            {
                if(dp3[j-temp.cost]<dp2[j]+temp.atk)
                {
                    dp3[j-temp.cost]=dp2[j]+temp.atk;
                    num[j-temp.cost]=i;
                }
            }
        }
        memcpy(dp4,dp3,sizeof(dp3));
        for(long long int i=0;i<c;i++)
        {
            temp=wuqi[i];
            for(long long int j=temp.cost;j<=m;j++)
            {
                if(i==num[j])
                    continue;
                if(dp4[j-temp.cost]<dp3[j]+temp.atk)
                    dp4[j-temp.cost]=dp3[j]+temp.atk;
            }
        }
        for(long long int i=0;i<d;i++)
        {
            temp=wuqi2[i];
            for(long long int j=temp.cost;j<=m;j++)
            {
                if(dp4[j-temp.cost]<dp2[j]+temp.atk)
                    dp4[j-temp.cost]=dp2[j]+temp.atk;
            }
        }
        long long int out=0;
        for(long long int i=0;i<=m;i++)
            out=max(out,dp4[i]);
        cout << out << endl;

        memset(dp1,0,sizeof(dp1));
        memset(dp2,0,sizeof(dp2));
        memset(dp3,0,sizeof(dp3));
        memset(dp4,0,sizeof(dp4));
        memset(num,-1,sizeof(num));
        memset(tou,0,sizeof(tou));
        memset(shou,0,sizeof(shou));
        memset(wuqi,0,sizeof(wuqi));
        memset(wuqi2,0,sizeof(wuqi2));
    }
    return 0;
}

Problem C: wintermelon的魔界寻路之旅
原题。

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define inf 100000000
#define MOD 1000000009
#define MAXV 210

int dx[4] = { 0, 0, 1, -1 }, dy[4] = { 1, -1, 0, 0 };
//用于bfs和dfs搜索的方向
int map[MAXV][MAXV], vol[MAXV][MAXV], n, dis[MAXV][MAXV], flag[MAXV][MAXV], res;
//map保存网格,vol保存从0,0到i,j的最短路,n表示网格大小
//dis与flag用于深搜剪枝,res保存的是网格的最短路径

bool istrue(int x, int y){ //判断x,y是否是合理的,即不能超过界限
    if (x < n && x >= 0 && y < n && y >= 0 && y < n - x) return true;
    return false;
}

void dijstra(){
    int x, y, tx, ty, i;
    queue <int>q;

    vol[0][0] = map[0][0];
    q.push(0);
    q.push(0);
    while (!q.empty()){ //求出了所有0,0到i,j的最短路
        x = q.front(); q.pop();
        y = q.front(); q.pop();

        for (i = 0; i<4; i++){
            tx = x + dx[i];
            ty = y + dy[i];
            if (istrue(tx, ty) && vol[tx][ty]>map[tx][ty] + vol[x][y]){
                q.push(tx);
                q.push(ty);
                vol[tx][ty] = map[tx][ty] + vol[x][y];
            }
        }
    }
    res = vol[0][n - 1];  //找出0,0到对称线上的最短路的最小值即是整个网格对称路径的最短路
    for (i = 0; i<n; i++)
    if (res>vol[i][n - i - 1]) res = vol[i][n - i - 1];
}

int dfs(int x, int y){
    int i, tx, ty;
    if (x == 0 && y == 0) return 1;

    //这两句剪枝用的很巧妙,不加的话就会超时,表示x,y是否是第一次搜索,
    //如果不是的话就直接返回,不用再次计算dis
    //dis[x][y]表示从x,y到0,0有多少条这样的路径
    if (flag[x][y]) return dis[x][y];
    flag[x][y] = true;

    dis[x][y] = 0;
    for (i = 0; i < 4; i++){
        tx = x + dx[i];
        ty = y + dy[i];
        if (istrue(tx, ty) && vol[x][y] == vol[tx][ty] + map[x][y]){
            dis[x][y] = (dis[x][y] + dfs(tx, ty)) % MOD;
        }
    }
    return dis[x][y];
}

int main(){
    int i, j, key;
    int t;
    cin >> t;
    while (t--)
    {
            scanf("%d", &n);
            for (i = 0; i < n; i++)
            for (j = 0; j < n; j++)
                scanf("%d", &map[i][j]);
            //优化,把下三角的值加到上三角上面,这样就把问题看成从0,0到对称线上的最短路,可以减少很多计算量
            for (i = 0; i < n; vol[i][j] = inf, i++)
            for (j = 0; j < n - i - 1; j++){
                map[i][j] = map[i][j] + map[n - j - 1][n - i - 1];
                vol[i][j] = inf;
            }

            dijstra();  //求出了最短路

            memset(flag, false, sizeof(flag));
            key = 0;  //计算相等路有多少条
            for (i = 0; i < n; i++)
            if (res == vol[i][n - i - 1])
                key = (key + dfs(i, n - i - 1)) % MOD;
            printf("%d\n", key);

    }

    return 0;
}

Problem D: 二叉树的中序遍历
超级简单题却被坑了,连续俩#就绝对是错的。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
using namespace std;
string str;
int t;
long long int l;
bool flag;
int last;
int now;
int main(void)
{
    cin >> t;
    while(t--)
    {
        cin >> str;
        l=str.length();
        flag=1;
        last=0;
        for(long long int i=0;i<l;i++)
        {
            if(str[i]=='#')
                last++;
            else
                last=0;
            if(last==2)
            {
                flag=0;
                break;
            }

        }
        if(flag)
            cout << "yes" << endl;
        else
            cout << "no" << endl;
    }
    return 0;
}

Problem E: 积木积水
水题

#include <iostream>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string.h>
#include <map>
#include <set>
using namespace std;


int T, N;
const int INF = 1000010;
int arr[INF];


int main(void){
    cin >> T;
    while(T --){
        cin >> N;
        long long ans = 0;
        int MAXX;
        for(int i= 0; i < N; i ++){
            scanf("%d", &arr[i]);
            if(i == 0){
                MAXX = arr[i];
                continue;
            }
            if(arr[i] <= MAXX){
                ans += MAXX - arr[i];
            }
            else{
                MAXX = arr[i];
            }
        }
        int MINN = 0;
        for(int i = N - 1; MINN != MAXX && i >= 0; i --){
            if(i == N - 1){
                MINN = arr[N - 1];
                ans -= MAXX - MINN;
                continue;
            }
            if(arr[i] <= MINN){
                ans -= MAXX - MINN;
            }
            else{
                MINN = arr[i];
                ans -= MAXX - MINN;
            }
        }
        cout << ans << endl;
    }
}

Problem F: 我是好人4
看队友的吧- -
http://chilumanxi.org/2016/04/21/gdut-2016-%E6%A0%A1%E8%B5%9Bf-%E6%88%91%E6%98%AF%E5%A5%BD%E4%BA%BA4/

Problem G: 我是水题
真是水题。。。

#include <iostream>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string.h>
#include <map>
#include <set>
using namespace std;


int T;
int arr[1000];
int main(void){
    cin >> T;
    getchar();
    while(T --){
        memset(arr, 0, sizeof(arr));
        int temp = 0;
        string tempstr;
        getline(cin, tempstr);
        for(int i = 0; i < tempstr.size(); i ++){
            if(tempstr[i] <= 'z' && tempstr[i] >= 'a'){
                if(!arr[tempstr[i] - 'a']){
                    arr[tempstr[i] - 'a'] ++;
                    temp ++;
                }

            }
        }
        cout << temp << endl;
    }
}

你可能感兴趣的:(ACM)