2018.10.27 练习赛

T1 蒜头君打地鼠

题解:

矩阵转换,坐标变一下二维前缀和,枚举中心,更新\(ans\)最大值

坐标关系:

\(X'=X+Y-1\);

\(Y'=N-(X-Y)\);

\(code\):

#include<cstdio>
#include<ctype.h>
#include<vector>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
//    return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    bool flag=0;
    while(!isdigit(tt=gc())&&tt!='-');
    tt=='-'?(flag=1,x=0):(x=tt-'0');
    while(isdigit(tt=gc())) x=x*10+tt-'0';
    if(flag) x=-x;
}

const int maxn=2002;
struct node{
    int x,y;
    inline node(int a=0,int b=0) 
    {x=a,y=b;}
}a[maxn*maxn];

int n,k,tot;
int m[maxn<<1][maxn<<1];
int w[maxn<<1][maxn<<1];
int main()
{
    read(n),read(k);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        int x;
        read(x);
        m[i+j-1][n-(i-j)]=x;
        a[++tot]=node(i+j-1,n-(i-j));
    }
    for(int i=1;i<=n<<1;i++)
    for(int j=1;j<=n<<1;j++)
    w[i][j]=w[i-1][j]+w[i][j-1]-w[i-1][j-1]+m[i][j];
    
//  for(int i=1;i<=n<<1;i++,putchar(10))
//  for(int j=1;j<=n<<1;j++)
//  printf("%d ",m[i][j]);
//  putchar(10);
//  for(int i=1;i<=n<<1;i++,putchar(10))
//  for(int j=1;j<=n<<1;j++)
//  printf("%d ",w[i][j]);
    
    int ans=0;
    for(int i=1;i<=tot;i++)
    {
        int x1,x2,y1,y2;
        x1=max(a[i].x-k+1,1);
        x2=min(a[i].x+k-1,(n<<1)-1);
        y1=max(a[i].y-k+1,1);
        y2=min(a[i].y+k-1,(n<<1)-1);
        ans=max(ans,w[x2][y2]-w[x1-1][y2]-w[x2][y1-1]+w[x1-1][y1-1]);
    }
    printf("%d",ans);
}

T2 蒜头君的树

题解:

统计子树贡献,\(ans=\sum sz[x]*(n-sz[x])*w[x]\),记住在乘法处需要类型转换!!!切记切记,改悔改悔

\(code:\)

#include<cstdio>
#include<ctype.h>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
//    return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    bool flag=0;
    while(!isdigit(tt=gc())&&tt!='-');
    tt=='-'?(flag=1,x=0):(x=tt-'0');
    while(isdigit(tt=gc())) x=x*10+tt-'0';
    if(flag) x=-x;
}

const int maxn=1e5+2;
ll ans;
ll n,m,sz[maxn],w[maxn];
vector<ll>G[maxn];

void dfs(ll x)
{
    sz[x]++;
    for(int i=G[x].size()-1;i>=0;i--)
    {
        int p=G[x][i];
        dfs(p);sz[x]+=sz[p];
    }
    ans+=sz[x]*(n-sz[x])*w[x];
}

int main()
{
    read(n);
    for(int i=1;i<n;i++)
    {
        ll x,y;
        read(x),read(y);
        G[x].push_back(i+1);
        w[i+1]=y;
    }
    dfs(1);
    printf("%lld\n",ans);
    read(m);
    while(m--)
    {
        int x,y;
        read(x),read(y);
        ans-=sz[x]*(n-sz[x])*w[x];
        w[x]=y;
        ans+=sz[x]*(n-sz[x])*w[x];
        printf("%lld\n",ans);
    }
}

T3 蒜头君的坐骑

题解:

棋盘\(DP\),设定状态为\(F[i][j][k]\),表示到达\((i,j)\)这点用了\(k\)个技能所消耗最小值,不用技能就向右边或下面转移,用技能就用\(dfs\)直接跑到目标点

\(code:\)

#include<cstdio>
#include<ctype.h>
#include<vector>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
//    return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    bool flag=0;
    while(!isdigit(tt=gc())&&tt!='-');
    tt=='-'?(flag=1,x=0):(x=tt-'0');
    while(isdigit(tt=gc())) x=x*10+tt-'0';
    if(flag) x=-x;
}

const int maxn=502;
int n,m,t,k,h,atk,w[maxn][maxn];
int f[maxn][maxn][10];

int cal(int x,int y,int z){return (h-1)/z*w[x][y];}

void merge(int &x,int y){x=min(x,y);}

void dfs(int x,int y,int num,int step,int atkk,int val)
{
    if(step) val+=cal(x,y,atkk);
    if(!(step^k)) {merge(f[x][y][num+1],val);return;}
    if(x^n) dfs(x+1,y,num,step+1,atkk+w[x+1][y],val);
    if(y^m) dfs(x,y+1,num,step+1,atkk+w[x][y+1],val);
}

int main()
{
    read(n),read(m),read(t),read(k),read(h),read(atk);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++) read(w[i][j]);
    
    memset(f,30,sizeof(f));f[1][1][0]=0;
    
    for(int num=0;num<=t;num++)
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        if(i^n) merge(f[i+1][j][num],f[i][j][num]+cal(i+1,j,atk));
        if(j^m) merge(f[i][j+1][num],f[i][j][num]+cal(i,j+1,atk));
        if(num^t) dfs(i,j,num,0,atk,f[i][j][num]);
    }
    printf("%d",f[n][m][t]);
}

猜你喜欢

转载自www.cnblogs.com/KatouKatou/p/9860782.html
今日推荐