晚上自虐拿前年杭州的题来刷。。果然是凶残,目测是4题打铁的节奏。。
hdu 4461 The Power of Xiangqi
题意:象棋每个棋子赋予了一定的战力,比较红方还是黑方战力高。
思路:略。
#include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<algorithm> #include<string.h> #include<cstdio> using namespace std; int power[]={16,7,8,1,1,2,3}; int main(){ int t; cin>>t; while(t--){ int pa=0; int pb=0; int na; cin>>na; bool checkc=0; bool checkb=0; for(int i=1;i<=na;i++){ char q[4]; cin>>q; pa+=power[q[0]-'A']; if(q[0]=='C')checkc=1; if(q[0]=='B')checkb=1; } if(!(checkc&&checkb)&&pa)pa--; int nb; cin>>nb; checkc=0; checkb=0; for(int i=1;i<=nb;i++){ char q[4]; cin>>q; pb+=power[q[0]-'A']; if(q[0]=='C')checkc=1; if(q[0]=='B')checkb=1; } if(!(checkc&&checkb)&&pb)pb--; if(pa==pb){ cout<<"tie"<<endl; }else if(pa>pb){ cout<<"red"<<endl; }else{ cout<<"black"<<endl; } } return 0; }
hdu 4463 Outlets
题意:求最小生成树,其中一条边必须连着。
思路:先连一条边,然后跑kruskal。
#include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<algorithm> #include<string.h> #include<cstdio> using namespace std; int x[55]; int y[55]; bool vis[55]; double dis[55][55]; struct edge{ int u,v; double len; }; edge E[50*50]; bool cmp(edge a,edge b){ return a.len<b.len; } double calc(int a,int b){ return sqrt( (x[a]-x[b])*(x[a]-x[b]) + (y[a]-y[b])*(y[a]-y[b]) ); } int p[55]; int find(int x){ if(x!=p[x])p[x]=find(p[x]); return p[x]; } void _union(int a,int b){ int fa=find(a); int fb=find(b); p[fa]=fb; find(a); } int main(){ int n; while(cin>>n){ if(!n)break; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++)p[i]=i; int a,b; cin>>a>>b; for(int i=1;i<=n;i++){ cin>>x[i]>>y[i]; } int end=0; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ dis[i][j]=dis[j][i]=calc(i,j); E[end].u=i; E[end].v=j; E[end++].len=calc(i,j); } } sort(E,E+end,cmp); _union(a,b); double ans=0.0; ans+=dis[a][b]; for(int t=2;t<n;t++){ for(int i=0;i<end;i++){ int u=E[i].u; int v=E[i].v; if(find(u)!=find(v)){ ans+=E[i].len; _union(u,v); break; } } } printf("%.2lf\n",ans); } return 0; }
hdu 4460 Friend Chains
题意:求图的直径。
思路:人名(字符串)用map映射到整数,然后根据关系建图。图直径的求法是随便找一个点x,找出离x最远的点u(如果有多个,取度最小的点),然后从u出发,找最远的点v,uv的距离就是图的直径。
#include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<map> #include<algorithm> #include<string.h> #include<cstdio> using namespace std; #define INF 1000000000 vector<int> E[2010]; bool vis[2010]; struct person{ int idx; int dis; }; person P[2010]; int main(){ int n; while(cin>>n){ if(!n)break; memset(E,0,sizeof(E)); map<string,int> mp; for(int i=1;i<=n;i++){ string str; cin>>str; mp[str]=i; } int m; cin>>m; for(int i=1;i<=m;i++){ string stra,strb; cin>>stra>>strb; int fa=mp[stra]; int fb=mp[strb]; E[ fa ].push_back( fb ); E[ fb ].push_back( fa ); } for(int i=1;i<=n;i++){ P[i].idx=i; P[i].dis=INF; } P[1].dis=0; memset(vis,0,sizeof(vis)); vis[1]=1; queue<person> que; que.push(P[1]); while(!que.empty()){ person cur=que.front(); que.pop(); int siz=E[cur.idx].size(); for(int i=0;i<siz;i++){ if(vis[E[cur.idx][i]])continue; P[ E[cur.idx][i] ].dis = cur.dis+1; que.push( P[ E[cur.idx][i] ] ); vis[E[cur.idx][i]]=1; } } int target; int _max=0; for(int i=2;i<=n;i++){ if(P[i].dis>_max|| (P[i].dis==_max&&E[i].size()<E[target].size()) ){ target=i; _max=P[i].dis; } } if(_max==INF){ cout<<-1<<endl; continue; } P[target].dis=0; memset(vis,0,sizeof(vis)); vis[target]=1; while(!que.empty())que.pop(); que.push(P[target]); while(!que.empty()){ person cur=que.front(); que.pop(); int siz=E[cur.idx].size(); for(int i=0;i<siz;i++){ if(vis[E[cur.idx][i]])continue; P[ E[cur.idx][i] ].dis = cur.dis+1; que.push( P[ E[cur.idx][i] ] ); vis[E[cur.idx][i]]=1; } } // int ans=0; for(int i=1;i<=n;i++){ if(P[i].dis>ans)ans=P[i].dis; } cout<<ans<<endl; } return 0; }
hdu 4462 Scaring the Birds
题意:一片N*N田地,有一些空地(至多10)可以插稻草人,每个地方插的稻草人能监视的距离为R(曼哈顿距离),问最少多少个稻草人能监视整片田。
思路:暴力。用10位二进制整数表示插稻草人的情况。对每种情况暴力判断每个格子是否被监视。注意能插稻草人的地方不用监视,特别是整片田都能插的情况。。。
#include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<map> #include<algorithm> #include<string.h> #include<cstdio> using namespace std; int r[12]; int c[12]; int R[12]; inline int MD(int x1,int y1,int x2,int y2){//曼哈顿距离 return abs(x1-x2)+abs(y1-y2); } int main(){ int n; while(cin>>n){ if(!n)break; int k; cin>>k; for(int i=1;i<=k;i++){ cin>>r[i]>>c[i]; } for(int i=1;i<=k;i++){ cin>>R[i]; } int end=1<<k; bool hasans=0; int re=10086; for(int q=0;q<end;q++){//从1开始循环坑了好多次。。 vector<int> ans; int tmp=q; int t=1; while(tmp){ if(tmp&1){ ans.push_back(t); } tmp>>=1; t++; } int siz=ans.size(); bool ok=1; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ bool flag=0; for(int w=1;w<=k;w++){ if(i==r[w]&&j==c[w])flag=1; } for(int w=0;w<siz;w++){ if( MD(i,j,r[ans[w]],c[ans[w]])<=R[ans[w]] ){ flag=1; break; } } if(!flag){ ok=0; break; } } } if(ok){ hasans=1; re=min(re,siz); } } if(hasans&&re!=10086){ cout<<re<<endl; }else{ cout<<-1<<endl; } } return 0; }