晚上自虐拿前年杭州的题来刷。。果然是凶残,目测是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;
}