A - The Willy Memorial Program
大模拟题……
一开始的思路不对,修修补补WA了十发。当时想直接一个并查集做连通来搞定它,结果发现不能很好地判断各管的水位。究其原因还是因为这个是跟进水的过程顺序有关的。
所以最后Ac的思路还是按模拟来做,在已经连通的管子中找最低的link连出去,不断更新水位,合并管子。
有些细节注意一下,AC~
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define INF 200000000
typedef long long ll;
int p,lk;
struct pipe{
int bot,top,lp;
}pp[30];
struct link{
int u,v,h;
}ln[60];
int fa[30],vis[60],hs[30],visp[30];
int cmp(struct link a,struct link b){
return a.h>b.h;
}
void init(){
for(int i=1;i<=p;i++)fa[i]=i;
}
int finds(int x){
return fa[x]!=x?fa[x]=finds(fa[x]):x;
}
void unions(int u,int v){
int fu=finds(u),fv=finds(v);
if(fu!=fv)fa[fu]=fv;
}
int main(){
//("a.in","r",stdin);freopen("a.out","w",stdout);
int t;
scanf("%d",&t);
while(t--){
memset(vis,0,sizeof vis);
memset(visp,0,sizeof visp);
scanf("%d",&p);
int left,up,hi;
for(int i=1;i<=p;i++){
scanf("%d%d%d",&left,&up,&hi);
pp[i].lp=left;pp[i].top=up;
pp[i].bot=up+hi;
}
scanf("%d",&lk);
for(int i=1;i<=lk;i++){
scanf("%d%d%d",&left,&ln[i].h,&hi);
for(int j=1;j<=p;j++)if(pp[j].bot>=ln[i].h&&pp[j].top<=ln[i].h){
if(pp[j].lp+1==left)ln[i].u=j;
if(pp[j].lp==left+hi)ln[i].v=j;
}
}
sort(ln+1,ln+lk+1,cmp);
int now=1,y=0,tar,h0,find=0,flag;
scanf("%d%d",&tar,&h0);
if(h0>pp[tar].bot||h0<=pp[tar].top){
printf("No Solution\n");
continue;
}
for(int i=1;i<=p;i++)hs[i]=pp[i].bot;
while(!find){
visp[now]=1;
if(now==tar)find=1;
if(find){
flag=1;
init();
for(int i=1;i<=lk&&ln[i].h>=h0;i++)unions(ln[i].u,ln[i].v);
for(int i=1;i<=p;i++)if(finds(i)==finds(tar)){
if(h0<=pp[i].top)flag=0;
hs[i]=min(hs[i],h0);
}
}else{
flag=0;
int pos;
for(pos=1;pos<=lk;pos++)if(!vis[pos])
if(visp[ln[pos].u]^visp[ln[pos].v]){flag=1;break;}
if(!flag)break;
now=visp[ln[pos].u]?ln[pos].u:ln[pos].v;
y=ln[pos].h;
vis[pos]=1;
init();
for(int i=1;i<=lk&&ln[i].h>y;i++)unions(ln[i].u,ln[i].v);
for(int i=1;i<=p;i++)if(finds(i)==finds(now))hs[i]=min(hs[i],y);
now=visp[ln[pos].v]?ln[pos].u:ln[pos].v;
}
}
for(int i=1;i<=p;i++)if(hs[i]<pp[i].top){flag=0;break;}
if(!flag){
printf("No Solution\n");
continue;
}
int ans=0;
for(int i=1;i<=p;i++)ans+=pp[i].bot-hs[i];
printf("%d\n",ans);
}
return 0;
}
C - Transmitters
暴力不多说……(必须有一个点在直径上)
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
int n,x0,y0,x[200],y[200];
double r;
int cal_above(double k){
int i,cnt=0;
for(i=0;i<n;i++)
if((x[i]-x0)*(x[i]-x0)+(y[i]-y0)*(y[i]-y0)<=r*r && y[i]>=y0+k*(x[i]-x0))
cnt++;
return cnt;
}
int cal_below(double k){
int i,cnt=0;
for(i=0;i<n;i++)
if((x[i]-x0)*(x[i]-x0)+(y[i]-y0)*(y[i]-y0)<=r*r && y[i]<=y0+k*(x[i]-x0))
cnt++;
return cnt;
}
int main(){//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
while(scanf("%d%d%lf",&x0,&y0,&r) && r>0){
int i,ans=0;
scanf("%d",&n);
for(i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]);
double k;
for(i=0;i<n;i++)if(x[i]!=x0){
k=(double)(y[i]-y0)/(x[i]-x0);
ans=max(ans,cal_above(k));
ans=max(ans,cal_below(k));
}
int c1=0,c2=0;
for(i=0;i<n;i++)if((x[i]-x0)*(x[i]-x0)+(y[i]-y0)*(y[i]-y0)<=r*r){
if(x[i]<=x0)c1++;
if(x[i]>=x0)c2++;
}
ans=max(ans,c1);ans=max(ans,c2);
printf("%d\n",ans);
}
return 0;
}
H - Mondriaan's Dream
一个经典的状压dp,需要用dfs搜索填充方案,然后按下一行的状态dp
<span style="font-size:18px;">#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
int h,w;
ll dp[20][1<<13];
void dfs(int sta,int cur,int ori,int beg){
dp[cur+1][sta]+=dp[cur][ori];
int bas=3<<beg;
for(int i=beg;i<=w-2;i++){
if((sta&bas)==0)
dfs(sta|bas,cur,ori,i+1);
bas<<=1;
}
}
int main(){
while(scanf("%d%d",&h,&w) && w){
int i,j,FULL=(1<<w)-1;
memset(dp,0,sizeof dp);
dp[0][FULL]=1;
for(i=0;i<h;i++)
for(j=0;j<(1<<w);j++){
dfs(FULL^j,i,j,0);
}
printf("%lld\n",dp[h][FULL]);
}
return 0;
}</span>
F - Space Station Shielding
因为这题知道了有一个小算法叫做 FloodFill ,简单来说就是bfs,从外面的点搜索所有可以reach的点,然后把周围如果和格子接触就染色。
这就相当于把所有在表面的面染色了。
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
int vis[80][80][80],g[80][80][80];
int ans,n,m,k,l;
int dx[6]={1,-1,0,0,0,0},dy[6]={0,0,1,-1,0,0},dz[6]={0,0,0,0,1,-1};
void bfs(int now){
int q[80*80*80],from=0,to=0;
q[to++]=now;
int vx,vy,vz,d,ux,uy,uz;
while(from<to){
vx=q[from]%n;
vy=(q[from]%(m*n))/n;
vz=q[from]/(m*n);
from++;
for(d=0;d<6;d++){
ux=vx+dx[d];
uy=vy+dy[d];
uz=vz+dz[d];
if(ux>=0&&ux<n && uy>=0&&uy<m && uz>=0&&uz<k && !vis[ux][uy][uz]){
if(g[ux][uy][uz])ans++;
else{
q[to++]=uz*m*n+uy*n+ux;
vis[ux][uy][uz]=1;
}
}
}
}
}
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
while(scanf("%d%d%d%d",&n,&m,&k,&l) && n){
memset(vis,0,sizeof vis);
memset(g,0,sizeof g);
int pos,x,y,z;
while(l--){
scanf("%d",&pos);
x=pos%n+1;
y=(pos%(m*n))/n+1;
z=pos/(m*n)+1;
g[x][y][z]=1;
}
n+=2;m+=2;k+=2;
ans=0;
int i,j;
for(i=0;i<m;i++)
for(j=0;j<k;j++)if(!vis[0][i][j])bfs(j*m*n+i*n+0);
for(i=0;i<m;i++)
for(j=0;j<k;j++)if(!vis[n-1][i][j])bfs(j*m*n+i*n+n-1);
for(i=0;i<n;i++)
for(j=0;j<k;j++)if(!vis[i][0][j])bfs(j*m*n+i);
for(i=0;i<n;i++)
for(j=0;j<k;j++)if(!vis[i][m-1][j])bfs(j*m*n+(m-1)*n+i);
for(i=0;i<n;i++)
for(j=0;j<m;j++)if(!vis[i][j][0])bfs(j*n+i);
for(i=0;i<n;i++)
for(j=0;j<m;j++)if(!vis[i][j][k-1])bfs(j*n+i+(k-1)*m*n);
printf("The number of faces needing shielding is %d.\n",ans);
}
return 0;
}
I - Hike on a Graph
bfs搜索~
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
#define N 51
typedef long long ll;
int g[60][60],vis[60][60][60],d[60][60][60];
int n,ans;
void bfs(int px,int py,int pz){
int q[60*60*60];
int from=0,to=0,ux,uy,uz;
q[to++]=px*N*N+py*N+pz;
while(from<to){
ux=q[from]/(N*N);
uy=(q[from]%(N*N))/N;
uz=q[from]%N;
vis[ux][uy][uz]=1;
if(ux==uy&&uy==uz){ans=d[ux][uy][uz];return;}
from++;
int i;
for(i=1;i<=n;i++)if(g[ux][i]==g[uy][uz]&&!vis[i][uy][uz]){
d[i][uy][uz]=min(d[i][uy][uz]>=0?d[i][uy][uz]:INF,1+d[ux][uy][uz]);
q[to++]=i*N*N+uy*N+uz;
}
for(i=1;i<=n;i++)if(g[uy][i]==g[uz][ux]&&!vis[ux][i][uz]){
d[ux][i][uz]=min(d[ux][i][uz]>=0?d[ux][i][uz]:INF,1+d[ux][uy][uz]);
q[to++]=ux*N*N+i*N+uz;
}
for(i=1;i<=n;i++)if(g[uz][i]==g[ux][uy]&&!vis[ux][uy][i]){
d[ux][uy][i]=min(d[ux][uy][i]>=0?d[ux][uy][i]:INF,1+d[ux][uy][uz]);
q[to++]=ux*N*N+uy*N+i;
}
}
}
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
int p1,p2,p3;
while(scanf("%d",&n) && n){
scanf("%d%d%d",&p1,&p2,&p3);
memset(vis,0,sizeof vis);
memset(d,-1,sizeof d);
memset(g,0,sizeof g);
int i,j;
char s[5];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
scanf("%s",s);
g[i][j]=s[0]-'a'+1;
}
ans=-1;
d[p1][p2][p3]=0;
bfs(p1,p2,p3);
if(ans>=0)printf("%d\n",ans);
else printf("impossible\n");
}
return 0;
}
G - Square Ice
模拟~我的做法是把逐个把0的状态定下来然后print
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
int g[30][30];
char sq[100][100];
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
int m,t=1;
while(scanf("%d",&m) && m){
int i,j;
memset(sq,0,sizeof sq);
memset(g,0,sizeof g);
for(i=0;i<m;i++)
for(j=0;j<m;j++)scanf("%d",&g[i][j]);
for(i=0;i<m;i++)
for(j=0;j<m;j++)if(!g[i][j]){
if(i && (g[i-1][j]==1||g[i-1][j]==6||g[i-1][j]==4))g[i][j]+=4;
if(!j || (g[i][j-1]==6||g[i][j-1]==2||g[i][j-1]==-1))g[i][j]+=2;
}
int px,py;;
for(i=0;i<m;i++)
for(j=0;j<m;j++){
px=i*4;py=j*4+2;
sq[px][py]='O';
if(g[i][j]==6||g[i][j]==4||g[i][j]==-1){sq[px-1][py]='|';sq[px-2][py]='H';}
if(g[i][j]==2||g[i][j]==0||g[i][j]==-1){sq[px+1][py]='|';sq[px+2][py]='H';}
if(g[i][j]==6||g[i][j]==2||g[i][j]==1){sq[px][py-1]='-';sq[px][py-2]='H';}
if(g[i][j]==4||g[i][j]==0||g[i][j]==1){sq[px][py+1]='-';sq[px][py+2]='H';}
}
if(t>1)printf("\n");
printf("Case %d:\n\n",t);
for(i=0;i<4*m+3;i++)printf("*");
printf("\n");
for(i=0;i<=4*m-4;i++){
printf("*");
for(j=0;j<=4*m;j++){
if(!sq[i][j])printf(" ");
else printf("%c",sq[i][j]);
}
printf("*\n");
}
for(i=0;i<4*m+3;i++)printf("*");
printf("\n");
t++;
}
return 0;
}
E - Sorting It All Out
拓扑排序
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <stack>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
int first[30],next[30*30],to[30*30],inc[30],g[30][30];
int n,m,edge;
int q[30],res;
int toposort(){
stack <int> s;
int i,du[30];
for(i=0;i<30;i++)du[i]=inc[i];
res=0;
for(i=1;i<=n;i++)if(!du[i])
s.push(i);
int u,e,v;
while(!s.empty()){
u=s.top();s.pop();
q[res++]=u;
e=first[u];
while(e!=-1){
du[to[e]]--;
if(!du[to[e]])s.push(to[e]);
e=next[e];
}
}
if(res<n)return -1;
for(i=0;i<n-1;i++)if(!g[q[i]][q[i+1]])return 0;
return 1;
}
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
char str[10];
while(scanf("%d%d",&n,&m) && n){
int u,v,flag=0;
memset(first,-1,sizeof first);
memset(next,-1,sizeof next);
memset(inc,0,sizeof inc);
memset(g,0,sizeof g);
edge=1;
for(int i=1;i<=m;i++){
scanf("%s",str);
if(flag)continue;
u=str[0]-'A'+1;
v=str[2]-'A'+1;
next[edge]=first[u];
first[u]=edge;to[edge++]=v;
inc[v]++;
g[u][v]=1;
res=0;
flag=toposort();
if(flag==1){
printf("Sorted sequence determined after %d relations: ",i);
for(int j=0;j<n;j++)printf("%c",'A'+q[j]-1);
printf(".\n");
}else if(flag==-1){
printf("Inconsistency found after %d relations.\n",i);
}
}
if(!flag)printf("Sorted sequence cannot be determined.\n");
}
return 0;
}
J - A Well-Formed Problem
这个是不是可以叫做蘑菇题了= =
一开始觉得hash,不过还是太麻烦改成了set……
模拟题实现起来也有很多可以学习的。做完看了一下watashi的代码觉得简直简洁啊!
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <stack>
#include <set>
#include <string>
#include <cctype>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
#define STACK_CLEAR while(!ele.empty())ele.pop();
#define SKIP(p) for(;*p==' ';p++);
#define GET(p) for(;isalnum(*p)||*p=='-';p++);
#define EAT(p) while(*p!='"'&&*p!='\0')p++;
typedef long long ll;
stack <string> ele;
set <string> st;
set <string> attr;
const char START[]= "<?xml version=\"1.0\"?>" ;
const char END[]="<?end?>";
int root;
char* addnew(char* s){
int shan=0;
char *p=s+1;
SKIP(p);
if(*p=='/')++p,shan=1;
attr.clear();
SKIP(p);
char *t0=p;
GET(p);
string t=string(t0,p);
SKIP(p);
while(*p!='>'&&*p!='/'&&*p){
char *s0=p;
GET(p);
string ar=string(s0,p);
/*for(;s0<p;s0++)printf("%c",*s0);
printf("\n");*/
if(attr.count(ar)>0)return NULL;
attr.insert(ar);
SKIP(p);
if(*p!='=')return NULL;
++p;SKIP(p);
if(*p!='"')return NULL;
++p;EAT(p);
if(*p=='\0')return NULL;
++p;SKIP(p);
}
if(shan){
if(ele.empty()||ele.top()!=t)return NULL;
ele.pop();
st.erase(t);
}else if(*p=='/'){
if(ele.empty())root++;
++p;SKIP(p);
}
else{
if(st.count(t)>0)return NULL;
if(ele.empty())root++;
ele.push(t);
st.insert(t);
}
if(*p!='>')return NULL;
return p;
}
int feed(char *p){
char *s=p;
while(*s){
if(*s=='<'){
s=addnew(s);
if(s==NULL)return 0;
}
else s++;
}
return 1;
}
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
char s[10010];
gets(s);
int flag=1;
while(strcmp(s,END)){
STACK_CLEAR;
st.clear();
gets(s);
flag=1;
root=0;
while(strcmp(s,START)&&strcmp(s,END)){
if(!flag||feed(s)==0)flag=0;
gets(s);
}
if(!flag||root!=1||!ele.empty())printf("non well-formed\n");
else printf("well-formed\n");
}
return 0;
}