目录
题目地址: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 n≤5000) 的数组 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;
}