AtCoder Beginner Contest 175



题目地址:https://atcoder.jp/contests/abc175/tasks



A Rainy Season

题意:水题

思路

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

int main()
{
    char s[10];
    scanf("%s",s);
    int ans=0;
    if(s[0]=='R' || s[1]=='R' || s[2]=='R') ans=1;
    if(s[0]=='R' && s[1]=='R') ans=2;
    if(s[1]=='R' && s[2]=='R') ans=2;
    if(s[0]=='R' && s[1]=='R' && s[2]=='R') ans=3;
    cout<<ans;

    return 0;
}



B Making Triangle

题意:水题。

思路

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

int main()
{
    int a[105],n;
    n=read();
    REP(i,1,n) a[i]=read();
    sort(a+1,a+n+1);
    int ans=0;
    for(int i=1;i<n;i++)
        for(int j=i+1;j<n;j++)
            for(int k=j+1;k<=n;k++)
                if(a[i]+a[j]>a[k] && a[i]!=a[j] && a[j]!=a[k])
                    ans++;
    cout<<ans;
    
    return 0;
}



C Walking Takahashi

题意

思路:水题

代码

x, k, d = map(int, input().split())
if x < 0:
    x = -x
if k * d <= x:
    print(x - k * d)
else:
    t = x // d
    x -= t * d
    k -= t
    if x >= d:
        x -= d
        k -= 1
    if k % 2 == 1:
        x -= d
    print(abs(x))



D Moving Piece

题意:一个长度为 n( n ≤ 5000 n\le 5000 n5000) 的数组 C,还有一个 1-n 的全排列 P,你可以随意选择一个元素开始游戏,然后跳至多 K 次,比如现在在 x,下一次就在 P[x]。问跳过的 C 之和最大是多少。

思路:因为 n 很小,所以可以对于每一个点,假设从它开始,然后处理出从它开始走多少步(环的大小以内)的收益是多少,然后讨论一下细节就可以了。

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=5005;
int n,k,p[maxn],c[maxn];
LL ans=1e-15;

int main()
{
    n=read(),k=read();
    REP(i,1,n) p[i]=read();
    REP(i,1,n) c[i]=read();
    REP(i,1,n)
    {
        int cur=i,be=i;
        VI s;
        s.pb(cur);
        LL y=c[cur];
        cur=p[cur];
        while(cur!=be)
        {
            s.pb(cur);
            y+=c[cur];
            cur=p[cur];
        }
        LL t=0;
        for(int i=0;i<s.size();i++)
        {
            t+=c[s[i]];
            if(i>=k) break;
            LL temp=t;
            if(y>0) temp+=(k-i-1)/s.size()*y;
            ans=max(ans,temp);
        }
    }
    if(ans==0) cout<<*max_element(c+1,c+n+1);
    else cout<<ans;
    //cout<<ans;

    return 0;
}



E Picking Goods

题意:给你一个 n 行 m 列的地图,有一些格点有一个正整数。你要从 (1, 1) 走到 (n, m),只能向右或者向下走,你经过了某个格点,如果这个格点上有正整数,你可以选择拿走,但是每一行至多拿走三个。问最多能拿走的值是多少。

思路:如果不限制拿走三个,那么就是一个特别简单的 dp,只用从上面和左边转移就行了,现在限制了个数,也不会很难,就设 f ( i , j , k ) f(i,j,k) f(i,j,k) 表示走到 (i, j) ,已经在这一行拿走了 k 个正整数的最大收益,然后一样的从上面和左边转移就行了。

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=3005;
LL a[maxn][maxn],f[maxn][maxn][4];

int main()
{
    int n=read(),m=read();
    int k=read();
    REP(i,1,k)
    {
        int x=read(),y=read(),v=read();
        a[x][y]=v;
    }
    REP(i,1,n) REP(j,1,m)
    {
        REP(k,0,3) f[i][j][k]=max(f[i][j-1][k],f[i-1][j][k]);
        if(a[i][j]>0)
        {
            REP(k,1,3) f[i][j][k]=max(f[i][j][k],f[i][j-1][k-1]+a[i][j]);
            REP(k,1,3) REP(kk,0,3)
                f[i][j][k]=max(f[i][j][k],f[i-1][j][kk]+a[i][j]);
        }
    }
    LL ans=0;
    REP(i,0,3) ans=max(ans,f[n][m][i]);
    cout<<ans;

    return 0;
}



F Making Palindrome

题意:给你 n 个字符串,每个字符串选择一次的花费为 C[i],现在你要从中选择若干个字符串(可以重复选择),使得拼接起来之后是一个回文串,并且花费最小。

思路:题目数据字符串长度和个数都很小,我们可以考虑列举出所有状态。每个状态有两个要素:字符串和位置。这里的字符串是指匹配过后的字符串,位置是指左边或者右边。比如说 左边的 abcd右边的 ba 进行匹配,可以得到 左边的 cd 。然后对于某个状态,如果要转移的话,就可以从字符串集中取字符串去配对,如果匹配成功就可以转移,转移的代价就是选择这个字符串的代价。所有的都建好之后,自定一个起点和终点,起点连向所有初始字符串,然后所有状态如果是回文串的就连向终点。最后求个最短路就行了。

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> PI;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=1e5+5;
typedef pair<string,int> psi;
map<psi,int> t;
struct edge {int v; LL w;};
vector<edge> G[maxn];
int n,m,c[maxn];
string s[maxn];

void add(int u,int v,int w)
{
    G[u].pb((edge){v,w});
}

bool huiwen(string v)
{
    if(v.length()<=1) return 1;
    int l=0,r=v.length()-1;
    while(l<r)
    {
        if(v[l]!=v[r]) return 0;
        l++,r--;
    }
    return 1;
}

int peidui(string left,string right,string &ret)
{
    int l=left.length(),r=right.length();
    int i=0,j=r-1;
    while(i<l && j>=0)
    {
        if(left[i]!=right[j]) return -1;
        i++; j--;
    }
    if(i>=l && j<0) {ret=""; return 0;}
    else if(j>=0) {ret=right.substr(0,j+1); return 1;}
    else if(i<l) {ret=left.substr(i,l); return 0;}
}

const LL inf=1e15+1;
LL d[maxn],vis[maxn];

void dijkstra(int s)
{
    fill(d,d+n+5,inf);
    //mem(vis,0);
    d[s]=0;
    typedef pair<LL,int> P;
    priority_queue<P,vector<P>,greater<P> > Q;
    Q.push(P(0,s));
    while(!Q.empty())
    {
        P p=Q.top(); Q.pop();
        LL dis=p.first,u=p.second;
        if(vis[u]) continue;
        d[u]=dis; vis[u]=1;
        REP(i,0,G[u].size()-1)
        {
            int v=G[u][i].v,w=G[u][i].w;
            if(vis[v] || dis+w>d[v]) continue;
            Q.push(P(d[v]=dis+w,v));
        }
    }
}

void print()
{
    for(map<psi,int>::iterator i=t.begin();i!=t.end();i++)
    {
        string v=i->first.first;
        int type=i->first.second;
        int id=i->second;
        cout<<v<<' '<<type<<' '<<id<<":   \n";
        for(edge e:G[id]) cout<<e.v<<' '<<e.w<<endl;
        cout<<endl;
    }
}

int main()
{
    m=read();
    REP(i,1,m)
    {
        cin>>s[i]>>c[i];
        int len=s[i].length();
        //cout<<s[i]<<' '<<len<<endl;
        for(int j=len-1;j>=0;j--)
            t[psi(s[i].substr(j,len),0)]=++n;
        for(int j=1;j<=len;j++)
            t[psi(s[i].substr(0,j),1)]=++n;
    }
    t[psi("",0)]=++n;
    t[psi("",1)]=++n;
    REP(i,1,m)
    {
        add(n+1,t[psi(s[i],0)],c[i]);
        add(n+1,t[psi(s[i],1)],c[i]);
    }
    for(map<psi,int>::iterator i=t.begin();i!=t.end();i++)
    {
        if(huiwen(i->first.first)) add(i->second,n+2,0);
    }

    for(map<psi,int>::iterator i=t.begin();i!=t.end();i++)
    {
        psi p=i->first;
        int id=i->second;
        for(int i=1;i<=m;i++)
        {
            string v;
            int ret;
            if(p.second==0) ret=peidui(p.first,s[i],v);
            else ret=peidui(s[i],p.first,v);
            if(ret!=-1)
            {
                add(t[p],t[psi(v,ret)],c[i]);
            }
        }
    }

    //print();

    dijkstra(n+1);
    if(d[n+2]>=inf) cout<<"-1";
    else cout<<d[n+2];

    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值