多校第八场解题报告

1003Mine

传送门

让人无限伤心的一道题。

这题是一道简单的sg函数取石子的题,题目中有几处需要注意的。

首先这不是传统意义上的扫雷的走法,白格的八向联通的。

然后是不存在同时属于两个白格范围的格子,也就是不存在同时属于两个石堆的石子。

我们把单独的格子记为1,雷记为0,白格区域周围有偶数格的话和单独的格子效果一样,记为1

周围是奇数个的话则会产生转换,记为2。

然后计算就行了。

比赛的时候的代码距离AC只差三个字符,极度伤心T_T(DFS的时候可能会暴栈,建议自定义栈大小)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;

int n,m,k;
int sum[1005][1005];
bool used[1005][1005];
int s[1000005];
int shu,shuk,ans;
int dx[10] = {1,1,0,-1,-1,-1,0,1};
int dy[10] = {0,-1,-1,-1,0,1,1,1};
int sx[5] = {1,0,-1,0};
int sy[5] = {0,-1,0,1};

void dfs(int x,int y)
{
    used[x][y] = 1;
    for(int i=0; i<8; i++)
    {
        if(x + dx[i] >= 0 && x + dx[i] < n &&y + dy[i] >= 0&&y + dy[i] < m)
        {
            if(used[x + dx[i]][y + dy[i]] == 0&&sum[x + dx[i]][y + dy[i]] == 0)
            {
                dfs(x + dx[i],y + dy[i]);
            }
        }
    }
    for(int i=0; i<8; i++)
    {
        if(x + dx[i] >= 0 && x + dx[i] < n &&y + dy[i] >= 0&&y + dy[i] < m)
        {
            if(used[x + dx[i]][y + dy[i]] == 0&&sum[x + dx[i]][y + dy[i]] > 0)
            {
                used[x + dx[i]][y + dy[i]] = 1;
                shuk++;
            }
        }

    }
}

int main()
{
    int t,counter;
    int a,b;
    while(scanf("%d",&t) != EOF)
    {
        counter = 0;
        while(t--)
        {
            counter++;
            scanf("%d%d%d",&n,&m,&k);
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<m; j++)
                {
                    sum[i][j] = 0;
                    used[i][j] = 0;
                }
            }
            for(int i=0; i<k; i++)
            {
                scanf("%d%d",&a,&b);
                for(int j=0; j<8; j++)
                {
                    if(a + dx[j] >= 0 && a + dx[j] < n &&b + dy[j] >= 0&&b + dy[j] < m)
                    {
                        sum[a + dx[j]][b + dy[j]]++;
                    }
                }
                used[a][b] = 1;
            }
            shu = 0;
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<m; j++)
                {
                    if(used[i][j] == 0)
                    {
                        if(sum[i][j] == 0)
                        {
                            shuk = 0;
                            dfs(i,j);
                            s[shu] = shuk % 2 + 1;//就是这里最初差了三个字符T_T
                            shu++;
                        }
                    }
                }
            }
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<m; j++)
                {
                    if(used[i][j] == 0)
                    {
                        s[shu] = 1;
                        shu++;
                    }
                }
            }
            ans = 0;
            for(int i=0; i<shu; i++)
            {
                //cout<<s[i]<<endl;
                ans ^= s[i];
            }
            printf("Case #%d: ",counter);
            if(ans)
            {
                printf("Xiemao\n");
            }
            else
            {
                printf("Fanglaoshi\n");
            }
        }
    }
    return 0;
}

1004Terrorist’s destroy

传送门

一道比较明显的树DP,就是写法比较繁琐

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

#define Max 2505
#define FI first
#define SE second
#define ll long long
#define PI acos(-1.0)
#define inf 0x7fffffff
#define LL(x) ( x << 1 )
#define bug puts("here")
#define PII pair<int,int>
#define RR(x) ( x << 1 | 1 )
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define infA(a) for (int i = 0 ; i <= n ; ++ i)a[i] = inf ;
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )

using namespace std;

inline void RD(int &ret)
{
    char c;
    do
    {
        c = getchar();
    }
    while(c < '0' || c > '9') ;
    ret = c - '0';
    while((c=getchar()) >= '0' && c <= '9')
        ret = ret * 10 + ( c - '0' );
}

inline void OT(int a)
{
    if(a >= 10)OT(a / 10) ;
    putchar(a % 10 + '0') ;
}
#define N 1000005
int n , m ;
struct kdq
{
    int s , e , l , id ;
} ed1[N] ;
int dis[N] , vis[N] ,qe[N * 10] ;
struct ee
{
    int e , next ,id ;
} ed[N * 5] ;
int ST , EN ;
int path[N] , pre[N] ;
int head[N] , num ;
void init()
{
    mem(head, -1) ;
    num = 0 ;
}
void add(int s ,int e ,int id)
{
    ed[num].e = e ;
    ed[num].id = id ;
    ed[num].next = head[s] ;
    head[s] = num ++ ;
}
int bfs(int pos)
{
    for (int i = 0 ; i <= n ; i ++ )
    {
        dis[i] = inf ;
        vis[i] = 0 ;
    }
    vis[pos] = 1 ;
    dis[pos] = 0 ;
    int h = 0 , t = 0 ;
    qe[h ++ ] = pos ;
    int ans = 0 ;
    int index = -1 ;
    while(h > t)
    {
        int tp = qe[t ++ ] ;
        for (int i = head[tp] ; ~i ; i = ed[i].next)
        {
            int e = ed[i].e ;
            if(dis[e] > dis[tp] + 1 && !vis[e])
            {
                dis[e] = dis[tp] + 1 ;
                pre[e] = tp ;
                path[e] = i ;
                vis[e] = 1 ;
                if(dis[e] > ans)
                {
                    ans = dis[e] ;
                    index = e ;
                }
                qe[h ++ ] = e ;
            }
        }
    }
    return index ;
}
int main()
{
    int T ;
    cin >> T ;
    int ca = 0 ;
    while(T -- )
    {
        cin >> n ;
        init() ;
        for (int i = 1 ; i <= n - 1 ; i ++ )
        {
            scanf("%d%d%d",&ed1[i].s ,&ed1[i].e , &ed1[i].l) ;
            ed1[i].id = i ;
            add(ed1[i].s , ed1[i].e , i) ;
            add(ed1[i].e , ed1[i].s , i) ;
        }
        ST = bfs(1) ;
        bfs(ST) ;
        int mm = 0 ;
        for (int i = 1 ; i <= n ; i ++ )
        {
            if(mm < dis[i])
            {
                mm = dis[i] ;
                EN = i ;
            }
        }
        int xx = 0 ;
        int yy = mm - 1 ;
        int MM = inf ;
        int index = -1 ;
        for (int i = EN ; i != ST ; i = pre[i])
        {
            int c = ed1[ed[path[i]].id].l ;
            int cc = max(xx , yy) ;
            if(MM > c * cc)
            {
                MM = c * cc ;
                index = ed[path[i]].id ;
            }
            else if(MM == c * cc)
            {
                index = min(index ,ed[path[i]].id) ;
            }
            xx ++ ,yy -- ;
        }
        printf("Case #%d: %d\n",++ca , index) ;
    }
    return 0 ;
}

1006string

传送门

全场最水的一道,不多说

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define Rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define LL long long
using namespace std;

const int N = 1111;

char A[N];
char B[N];
char C[N];
int qian[N][N];
int hou[N][N];
vector<pair<int, int> >atA;
vector<pair<int, int> >atB;


int main()
{
    int T;
    scanf("%d", &T);
    for(int t=1; t<=T; ++t)
    {
        scanf("%s%s%s", A+1, B+1, C+1);
        int lA = strlen(A+1);
        int lB = strlen(B+1);
        int lC = strlen(C+1);
        memset(qian, 0, sizeof(qian));
        memset(hou, 0, sizeof(hou));
        for(int i=1; i<=lA; ++i)
        {
            for(int j=1; j<=lB; ++j)
            {
                qian[i][j] = qian[i-1][j-1]+(A[i]==B[j]?1:0);
                qian[i][j] = max(qian[i][j], qian[i-1][j]);
                qian[i][j] = max(qian[i][j], qian[i][j-1]);
            }
        }
        for(int i=lA; i>=1; --i)
        {
            for(int j=lB; j>=1; --j)
            {
                hou[i][j] = max(hou[i+1][j], hou[i][j+1]);
                hou[i][j] = max(hou[i][j], hou[i+1][j+1]+(A[i]==B[j]?1:0));
            }
        }
        atA.clear();
        atB.clear();
        for(int i=1; i<=lA; ++i)
        {
            if(A[i]==C[1])
            {
                int j=2, ii=i+1;
                for(; j<=lC; )
                {
                    while(ii<=lA && A[ii]!=C[j]) ++ii;
                    if(ii>lA) break;
                    ++ii;
                    ++j;
                }
                if(j>lC)
                {
                    atA.push_back(make_pair(i, ii-1));
                }
            }
        }
        for(int i=1; i<=lB; ++i)
        {
            if(B[i]==C[1])
            {
                int j=2, ii=i+1;
                for(; j<=lC;)
                {
                    while(ii<=lB && B[ii]!=C[j]) ++ii;
                    if(ii>lB) break;
                    ++ii;
                    ++j;
                }
                if(j>lC) atB.push_back(make_pair(i, ii-1));
            }
        }

        int aa = atA.size();
        int bb = atB.size();
        int ans = 0;
        for(int i=0; i<aa; ++i)
        {
            for(int j=0; j<bb; ++j)
            {
                ans = max(ans, qian[atA[i].first-1][atB[j].first-1]+hou[atA[i].second+1][atB[j].second+1]);
            }
        }
        printf("Case #%d: %d\n", t, ans+lC);

    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值