木棒游戏
(传送门)
题意
木棒拼成的等式,移动一根木棒,使等式成立
分析
傻逼的模拟题
移动一根火柴可以分为两种情况:
一是移动某一个数字上的一根火柴,使之变为另一个数字。
二是两个数字,一个添加一根火柴,一个减少一根火柴。
弄清楚了原理就多重循环模拟吧
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1010;
char s[MAXN];
int n,m,i,j,I,J,k,t,a[10][10],b[10][10],ppow[8],v[MAXN],w[MAXN],e[MAXN][8],l[MAXN],pos;
long long sum,tmp;
void ok()
{
for(i=1;i<=pos;i++)
{
if(i>1) putchar(w[i]==1?'+':'-');
else if(w[i]!=1)putchar('-');
for(j=l[i]-1;~j;j--)
printf("%d",e[i][j]);
}
for(putchar('=');i<=n;i++)
{
if(i>pos+1) putchar(w[i]==1?'-':'+');
else if(w[i]==1)putchar('-');
for(j=l[i]-1;~j;j--)
printf("%d",e[i][j]);
}
putchar('#');
exit(0);
}
void _do()
{
(v[n]*=10)+=s[i]-'0';
e[n][l[n]++]=s[i]-'0';
}
int main()
{
for(ppow[0]=i=1;i<8;i++)
ppow[i]=ppow[i-1]*10;
a[0][6]=a[0][9]=a[2][3]=a[3][2]=a[3][5]=a[5][3]=a[6][0]=a[6][9]=a[9][0]=a[9][6]=1
b[0][8]=b[1][7]=b[3][9]=b[5][6]=b[5][9]=b[6][8]=b[9][8]=1;
scanf("%s",s+1);
n=strlen(s+1);
if(s[1]=='-')
for(w[n=1]=-1,i=2;s[i]>='0'&&s[i]<='9';i++) _do();
else
for(w[n=1]=i=1;s[i]>='0'&&s[i]<='9';i++) _do();
while(s[i]!='=')
for(w[++n]=s[i++]=='+'?1:-1;s[i]>='0'&&s[i]<='9';i++) _do();
pos=n;
if(s[++i]=='-')
for(w[++n]=1,i++;s[i]>='0'&&s[i]<='9';i++) _do();
else
for(w[++n]=-1;s[i]>='0'&&s[i]<='9';i++) _do();
while(s[i]!='#')
for(w[++n]=s[i++]=='-'?1:-1;s[i]>='0'&&s[i]<='9';i++) _do();
for(i=1;i<=n;i++)
for(sum+=v[i]*w[i],j=0,k=l[i]-1;j<k;j++,k--)
swap(e[i][j],e[i][k]);
for(i=1;i<=n;i++)
for(j=0;j<l[i];j++)
for(t=0;t<=9;t++)
if(a[e[i][j]][t])
{
tmp=sum+w[i]*(t-e[i][j])*ppow[j];
if(!tmp)e[i][j]=t,ok();
}
for(i=1;i<=n;i++)
for(j=0;j<l[i];j++)
for(I=1;I<=n;I++)
for(J=0;J<l[I];J++)
if(!(i==I&&j==J))
for(k=0;k<=9;k++)
for(t=0;t<=9;t++)
if(b[e[i][j]][k]&&b[t][e[I][J]])
{
tmp=sum+w[i]*(k-e[i][j])*ppow[j]+w[I]*(t-e[I][J])*ppow[J];
if(!tmp)e[i][j]=k,e[I][J]=t,ok();
}
return puts("No"),0;
}
文本编辑器
(传送门)
题意
对于给定的要求,支持光标的跳转,前移后移,及某处开始的插入,删除,输出操作
分析
看到一大堆操作,数据结构题,又看到了这个题有可以跳转什么的,splay可搞定
但是没有翻转之类的操作,写splay显然有些大材小用了,STL中的块状链表也可以完美的解决(简直就是bug)。
代码
#include <iostream>
#include <cstdio>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
crope list;
char ch[3000005];
int main()
{
int t,x,now=0;
cin>>t;
char s[10];
while(t--)
{
scanf("%s",s);
switch(s[0])
{
case 'M': scanf("%d",&now); break;
case 'P': now--; break;
case 'N': now++; break;
case 'D': scanf("%d",&x); list.erase(now,x); break;
case 'G': scanf("%d",&x); list.copy(now,x,ch); ch[x]=0; printf("%s\n",ch); break;
case 'I':
scanf("%d",&x);
for(int i=0;i<x;i++)
{
ch[i]=getchar();
while(ch[i]=='\n')ch[i]=getchar();
}
ch[x]=0;
list.insert(now,ch);
}
}
return 0;
}
数据生成器
(传送门)
题意
从一棵树中找出三个点A,B,C,使得min(dis[A][C],dis[B][C])+dis[A][B]最大,求这个最大值
分析
这道题显然是Tree_Dp问题,在这儿可以想象别的方法
仔细想想,当min(dis[A][C],dis[B][C])+dis[A][B]取最大值时,路径AB是整个树的直径(最长链),
所以可以通过BFS找出树的直径后,直接枚举点C即可得到最大答案。
所以可以通过BFS找出树的直径后,直接枚举点C即可得到最大答案。
这样虽然稍微慢了一些,但无疑好想又好写。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=200000+5;
struct Edge
{
int u,v,w,next;
}edges[MAXN*2];
int head[MAXN],tot=0;
void addEdge(int u,int v,int w)
{
edges[++tot]=(Edge){u,v,w,head[u]};
head[u]=tot;
}
int n,m;
int BFS(int S,long long dist[])//求出每个点到S的距离,保存在dist[]数组里,并返回距离S最远的点
{
int ans=0;//最远点
bool vis[MAXN];
memset(vis,0,sizeof(vis));
int Q[MAXN],h=0,t=1;
dist[S]=0,Q[h]=S,vis[S]=1;
while(h<t)
{
int u=Q[h++];
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(vis[v]) continue;
dist[v]=dist[u]+edges[p].w;
if(dist[v]>dist[ans]) ans=v;
Q[t++]=v;
vis[v]=2;
}
}
return ans;
}
long long dista[MAXN],distb[MAXN];
int main()
{
memset(head,-1,sizeof(head));
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addEdge(u,v,w);
addEdge(v,u,w);
}
int a=BFS(1,dista);
int b=BFS(a,dista);
BFS(b,distb);
long long ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,min(dista[i],distb[i]));
ans+=dista[b];
cout<<ans<<endl;
return 0;
}
智破连环阵
(传送门)
题意
给出地图上N个目标点,M台武器(只能用一次)。每个武器启动后,将距它距离不超过K范围内的符合要求的目标全部摧毁
(要求:摧毁目标必须按编号顺序,而且同一时刻只有一个武器是启动的),求摧毁全部目标需要动多少武器
(要求:摧毁目标必须按编号顺序,而且同一时刻只有一个武器是启动的),求摧毁全部目标需要动多少武器
分析
部分搜索+二分图匹配,模型应该很好想
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=100+10;
const int INF=0x3f3f3f3f;
int n,m,f,point=0,res=INF;
int pos[MAXN][2],wea[MAXN][2],m[MAXN][MAXN],map[MAXN][MAXN],cov[MAXN],x[MAXN][MAXN],dis[MAXN];
bool bomb[MAXN][MAXN],len[MAXN][MAXN],vis[MAXN];
int dist(int a,int b)
{
return a*a+b*b;
}
void Add(int u,int v)
{
for(int i=1;i<=m;i++)
if(m[i][u]==v)
x[point][++x[point][0]]=i;
}
int Hungary(int u)
{
if(vis[u]) return 0;
vis[u]=1;
for(int i=1;i<=x[u][0];i++)
{
int v=x[u][i];
if(!cov[v] || Hungary(cov[v]))
{
cov[v]=u;
return v;
}
}
return 0;
}
void dfs(int i)
{
if(i>n) res=min(res,point);
if(point+dis[i]>=res) return;
point++;
x[point][0]=0;
for(int u=map[i][0];u>0;u--)
{
int t=map[i][u];
Add(i,t);
memset(vis,0,sizeof(vis));
int tt=Hungary(point);
if(tt)
{
dfs(t+1);
cov[tt]=0;
}
}
point--;
}
int main()
{
cin>>n>>m>>f;
for(int i=1;i<=n;i++)
scanf("%d%d",&pos[i][0],&pos[i][1]);
for(int i=1;i<=m;i++)
scanf("%d%d",&wea[i][0],&wea[i][1]);
f*=f;
for(int i=n;i>0;i--)
for(int j=m;j>0;j--)
if(dist(pos[i][0]-wea[j][0],pos[i][1]-wea[j][1])<=f)
bomb[j][i]=1;
for(int i=1;i<=m;i++)
{
m[i][n+1]=n;
for(int j=n;j>0;j--)
if(bomb[i][j])
{
m[i][j]=m[i][j+1];
len[j][m[i][j]]=1;
}
else m[i][j]=j-1;
}
for(int i=n;i>0;i--)
for(j=i;j<=n;j++)
if(len[i][j])
map[i][++map[i][0]]=j;
dis[n+1]=0;
for(int i=n;i>0;i--)
dis[i]=1+dis[map[i][map[i][0]]+1];
dfs(1);
cout<<res<<endl;
return 0;
}