World Final的题做的人太少了网上也找不到题解,蒟蒻只好挑几道水题做做啦。
A.Amalgamated Artichokes
sb题,记录一下前缀最大值就行了。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int p,a,b,c,d,n;
double ans,price[1000005];
inline double calc(int k)
{
return (double)p*(sin(a*k+b)+cos(c*k+d)+2);
}
int main()
{
scanf("%d%d%d%d%d%d",&p,&a,&b,&c,&d,&n);
for (int i=1;i<=n;i++)
price[i]=calc(i);
double mx=price[1];
for (int i=2;i<=n;i++)
{
ans=max(ans,mx-price[i]);
mx=max(mx,price[i]);
}
printf("%.6lf\n",ans);
return 0;
}
C.Catering
有上下界的费用流。
首先将人拆点,加上下界为1的流量限制,从源点发出K的流量,然后可以相互转移的连边加上费用,直接跑就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=210;
const int M=30005;
const int mod=210;
const int inf=1000000007;
int head[N],dis[N],path[N],q[N];
int list[M],next[M],flow[M],from[M],cost[M];
bool vis[N];
int n,k,A,S,T,SS,TT,cnt,ans;
inline void insert(int x,int y,int z,int w)
{
next[++cnt]=head[x];
head[x]=cnt;
from[cnt]=x;
list[cnt]=y;
flow[cnt]=z;
cost[cnt]=w;
}
inline bool spfa()
{
for (int i=0;i<=TT;i++) dis[i]=inf;
int t=0,w=1,x;
q[1]=SS; vis[SS]=true; dis[SS]=0;
while (t!=w)
{
t=(t+1)%mod;
x=q[t];
for (int i=head[x];i;i=next[i])
if (flow[i]&&dis[list[i]]>dis[x]+cost[i])
{
dis[list[i]]=dis[x]+cost[i];
path[list[i]]=i;
if (!vis[list[i]])
{
vis[list[i]]=true;
w=(w+1)%mod;
q[w]=list[i];
}
}
vis[x]=false;
}
return dis[TT]!=inf;
}
inline void mcf()
{
int x=inf;
for (int i=path[TT];i;i=path[from[i]]) x=min(x,flow[i]);
for (int i=path[TT];i;i=path[from[i]])
flow[i]-=x,flow[i^1]+=x,ans+=x*cost[i];
}
int main()
{
scanf("%d%d",&n,&k);
S=0; A=n<<1|1; T=A+1; SS=T+1; TT=SS+1; cnt=1;
for (int i=0;i<n;i++)
for (int j=1;j<=n-i;j++)
{
int x;
scanf("%d",&x);
if (!i)
insert(A,i+j,1,x),insert(i+j,A,0,-x);
else
insert(i+n,i+j,1,x),insert(i+j,i+n,0,-x);
}
for (int i=1;i<=n;i++)
insert(i+n,T,1,0),insert(T,i+n,0,0);
insert(S,A,k,0); insert(A,S,0,0);
for (int i=1;i<=n;i++)
insert(i,TT,1,0),insert(TT,i,0,0);
for (int i=1;i<=n;i++)
insert(SS,i+n,1,0),insert(i+n,SS,0,0);
insert(T,S,inf,0); insert(S,T,0,0);
while (spfa()) mcf();
cout << ans << endl;
return 0;
}
F.Keyboarding
fi,j,k
表示走到点
(i,j)
已经打了
k
个的最小步数,然后
注意可以在一个点打多次,开始没看到WA了一发。
#include<iostream>
#include<cstdio>
#include<queue>
#include<map>
#include<cstdlib>
#include<cstring>
#define pii pair<int,int>
using namespace std;
const int N=51;
const int L=10005;
const int INF=1000000007;
const int dx[4]={-1,0,0,1};
const int dy[4]={0,1,-1,0};
int n,m,len,ans=INF;
pii next[N][N][4];
bool vis[N][N][L];
char s[N][N],T[L];
struct node
{
int x,y,step,total;
};
inline bool in(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
}
inline void pre()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int k=0;k<4;k++)
{
int x=i+dx[k],y=j+dy[k];
while (s[x][y]==s[i][j]&&in(x,y)) x=x+dx[k],y=y+dy[k];
next[i][j][k]=make_pair(x,y);
}
}
inline void BFS()
{
queue<node> q;
if (s[1][1]==T[1]) q.push((node){1,1,1,1}),vis[1][1][1]=true;
else q.push((node){1,1,0,0}),vis[1][1][0]=true;
while (!q.empty())
{
node now=q.front(); q.pop();
// cout << now.x << " " << now.y << " " << now.step << " " << now.total << endl;
// system("pause");
if (s[now.x][now.y]==T[now.step+1]&&!vis[now.x][now.y][now.step+1])
{
vis[now.x][now.y][now.step+1]=true;
q.push((node){now.x,now.y,now.step+1,now.total+1});
}
for (int k=0;k<4;k++)
{
pii nxt=next[now.x][now.y][k];
if (!in(nxt.first,nxt.second)) continue;
int x=nxt.first,y=nxt.second;
if (T[now.step+1]==s[x][y])
{
if (vis[x][y][now.step+1]) continue;
vis[x][y][now.step+1]=true;
q.push((node){x,y,now.step+1,now.total+2});
if (now.step+1==len) ans=min(ans,now.total+2);
}
else
{
if (vis[x][y][now.step]) continue;
vis[x][y][now.step]=true;
q.push((node){x,y,now.step,now.total+1});
}
}
}
}
int main()
{
// freopen("keyboard.in","r",stdin);
// freopen("keyboard.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%s",s[i]+1);
scanf("%s",T+1);
len=strlen(T+1)+1;
T[len]='*';
pre();
BFS();
cout << ans << endl;
return 0;
}