A - Dinner
NBUT - 1217
题意
给你n个单词,从中找出和厨具有关的单词。
厨具有关的单词只有四个:bowl, knife, fork and chopsticks
很简单,就直接模拟就好了,控制一下输出的格式,比赛的时候没管太多。。代码写的有点长。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char a[100005];
int main()
{
int n;
while(~scanf("%d",&n))
{
int flag=0;
while(n--)
{
scanf("%s",a);
if(strcmp(a,"bowl")==0)
{
if(!flag)
printf("%s",a);
else
printf(" %s",a);
flag=1;
}
else if(strcmp(a,"knife")==0)
{
if(!flag)
printf("%s",a);
else
printf(" %s",a);
flag=1;
}
else if(strcmp(a,"fork")==0)
{
if(!flag)
printf("%s",a);
else
printf(" %s",a);
flag=1;
}
else if(strcmp(a,"chopsticks")==0)
{
if(!flag)
printf("%s",a);
else
printf(" %s",a);
flag=1;
}
}
printf("\n");
}
return 0;
}
·
·
You are my brother
NBUT - 1218
题意
有A和B两个在很久之前是一家人,由于过了太久,辈分有些乱,现在A想知道B是他平辈,低辈还是长辈
给你m条关系,每个关系有两个数字x,y,意思是y是x的父亲,A的数字代号是1,B的数字代号是2,如果B比A年轻,打印“You are my younger”。否则,如果B是A的长者,打印“You are my elder”。否则,打印“You are my brother”
解
每条关系都连接起来,比如存一下a的父亲是谁,连成一个树(线)一样的结构
从1(A)开始,找他的父亲,父亲的父亲…直到搜索到他们最大的公共祖宗,记录1到最大的祖宗中间一共有多少代,2页一样,比较他们两个到最大祖宗之间代数的大小
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[10005],ans;
void dfs(int u)//搜他们的父亲,父亲的父亲...直到那个最大的公共祖先
{
if(u==-1)
return ;
ans++;
dfs(a[u]);
}
int main()
{
int n,x,y;
while(~scanf("%d",&n))
{
memset(a,-1,sizeof(a));
for(int i=1;i<=n;i++)
{
scanf("%d %d",&x,&y);
a[x]=y;//存储关系
}
ans=0;
dfs(1);
int t1=ans;
ans=0;
dfs(2);
int t2=ans;
if(t1==t2)//比较他们之间的辈分层数
printf("You are my brother\n");
else if(t1>t2)
printf("You are my elder\n");
else
printf("You are my younger\n");
}
return 0;
}
·
·
Time
NBUT - 1219
题意:
用 ”|”,”_”和” “打印123456789,每次输入四份数字,打印出来
大概思路就是一行一行的打,每行里一个数字一个数字的打
天哪,这个题真的是大型模拟爆炸现场。。。打的吐血… …比赛的时候也没管太多。。代码写的又臭又长。。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
void p1(int x)
{
if(x==1)
{
printf(" ");
}
else if(x==2)
{
printf(" _ ");
}
else if(x==3)
{
printf(" _ ");
}
else if(x==4)
{
printf(" ");
}
else if(x==5)
{
printf(" _ ");
}
else if(x==6)
{
printf(" _ ");
}
else if(x==7)
{
printf(" _ ");
}
else if(x==8)
{
printf(" _ ");
}
else if(x==9)
{
printf(" _ ");
}
else if(x==0)
{
printf(" _ ");
}
}
void p2(int x)
{
if(x==1)
{
printf(" |");
}
else if(x==2)
{
printf(" _|");
}
else if(x==3)
{
printf(" _|");
}
else if(x==4)
{
printf("|_|");
}
else if(x==5)
{
printf("|_ ");
}
else if(x==6)
{
printf("|_ ");
}
else if(x==7)
{
printf(" |");
}
else if(x==8)
{
printf("|_|");
}
else if(x==9)
{
printf("|_|");
}
else if(x==0)
{
printf("| |");
}
}
void p3(int x)
{
if(x==1)
{
printf(" |");
}
else if(x==2)
{
printf("|_ ");
}
else if(x==3)
{
printf(" _|");
}
else if(x==4)
{
printf(" |");
}
else if(x==5)
{
printf(" _|");
}
else if(x==6)
{
printf("|_|");
}
else if(x==7)
{
printf(" |");
}
else if(x==8)
{
printf("|_|");
}
else if(x==9)
{
printf(" _|");
}
else if(x==0)
{
printf("|_|");
}
}
void f1(int a,int b,int c,int d)
{
p1(a);
p1(b);
p1(c);
p1(d);
printf("\n");
}
void f2(int a,int b,int c,int d)
{
p2(a);
p2(b);
p2(c);
p2(d);
printf("\n");
}
void f3(int a,int b,int c,int d)
{
p3(a);
p3(b);
p3(c);
p3(d);
printf("\n");
}
int main()
{
int a,b,c,d;
while(~scanf("%d",&a))
{
scanf("%d %d %d",&b,&c,&d);
f1(a,b,c,d);
f2(a,b,c,d);
f3(a,b,c,d);
}
return 0;
}
·
·
D - SPY
NBUT - 1220
英语真的是爆炸 … … … … 到现在我也没搞懂什么间谍不间谍的,反正这道题要做的就是给你三行单词,从第二行中,找出第一行有的但是第三行没有的… … … 如此简单的题。。。硬是翻译不出来。。。。被自己气死。。。
用map模拟一下就好了
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
map<string,int>ma1;
map<string,int>ma2;
string aa[100005];
int ji[100005];
int main()
{
int a,b,c;
while(~scanf("%d %d %d",&a,&b,&c))
{
ma1.clear();
ma2.clear();
string x;
for(int i=1;i<=a;i++)
{
cin>>x;
ma1[x]++;
}
for(int i=1;i<=b;i++)
{
cin>>x;
aa[i]=x;
}
for(int i=1;i<=c;i++)
{
cin>>x;
ma2[x]++;
}
int ans=0;
for(int i=1;i<=b;i++)
{
if(ma1[aa[i]]&&!ma2[aa[i]])
{
ji[ans++]=i;
}
}
if(ans==0)
printf("No enemy spy\n");
else
{
for(int i=0;i<ans;i++)
{
if(i==ans-1)
{
cout<<aa[ji[i]];
printf("\n");
}
else
{
cout<<aa[ji[i]];
printf(" ");
}
}
}
}
return 0;
}
·
·
E - Intermediary
NBUT - 1221
题意
一共有n个相互都不认识的人(编号0~n-1),有m个中间介绍人(编号0—m-1)
如果介绍人z可以把x介绍给y那么第一次需要d元的介绍费,第二次需要d+e元介绍费,第三次及以上需要d+e+f元介绍费(介绍费都由x承担)(z可以把x介绍给y不代表z可以将y介绍给x)
现在0号员工想认识n-1号员工,x最少需要支付多少元的介绍费
输入:
第一行三个整数n,m,p员工数,介绍人数,介绍关系数
第二行m个数代表了这m个介绍人的e值
第三行m个数代表了这m个介绍人的f值
接下来p行 每行四个数x,y,z,d 代表x可以认识y通过第z个介绍人第一次需要花费d元
思路
这道题翻译出来也是费了老劲了… … …
这个最短路是可以想到的,但是我们需要记录每次的状态,第z个介绍人向x介绍y介绍了几次
因为一共只有9个介绍人,有3个状态,所以用三进制状压表示
dis[i][j]:第i个点的第j个状态下的需要花费的最小值
这其中状态的表示是这样的:每个介绍人介绍了多少次(第一个介绍人介绍了一次就是1,第二个介绍人介绍了一次就是3(三进制表示))
其他的就是最短路了
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int th[15],c1[15],c2[15],fi[105],re[15];
int n,m,p,x,y,z,k,tot;
const int inf=0x3f3f3f3f;
int dis[105][20000];
struct node
{
int v,nex,w,id;
};
node e[50005];
struct Node
{
int u,cnt,dis;
Node(int U,int Cnt,int Dis)
{
u=U;
cnt=Cnt;
dis=Dis;
}
bool operator < (const Node&x)const
{
return dis>x.dis;
}
};
void add(int u,int v,int z,int w)
{
e[tot].v=v;
e[tot].id=z;
e[tot].w=w;
e[tot].nex=fi[u];
fi[u]=tot++;
}
void dij()
{
for(int i=0; i<n; i++)
for(int j=0; j<th[m]; j++)
dis[i][j]=inf;
dis[0][0]=0;
priority_queue<Node>q;//优先队列
q.push(Node(0,0,0));
while(!q.empty())
{
Node a=q.top();
q.pop();
if(a.dis>dis[a.u][a.cnt])
continue;
if(a.u==n-1)
{
printf("%d\n",a.dis);
return ;
}
int u=a.u;
for(int i=fi[u];i!=-1;i=e[i].nex)
{
int tmp=a.cnt;
for(int j=0;j<9;j++)//第j个介绍了re【j】次
{
re[j]=tmp%3;
tmp/=3;
}
int v=e[i].v,z=e[i].id,d=e[i].w,t=1;//t代表了这次要不要在加上一个状态,因为如果大于三次的话就不需要再加了
if(re[z]==1)
d+=c1[z];
else if(re[z]==2)
{
d+=c2[z];
t=0;
}
if(dis[v][a.cnt+t*th[z]]>a.dis+d)//松弛
{
dis[v][a.cnt+t*th[z]]=a.dis+d;
q.push(Node(v,a.cnt+t*th[z],a.dis+d));
}
}
}
printf("-1\n");
}
int main()
{
th[0]=1;
for(int i=1; i<=9; i++)//初始化
th[i]=th[i-1]*3;
while(~scanf("%d %d %d",&n,&m,&p))
{
tot=0;
memset(fi,-1,sizeof(fi));
for(int i=0; i<m; i++)
scanf("%d",&c1[i]);
for(int i=0; i<m; i++)
scanf("%d",&c2[i]);
for(int i=1; i<=p; i++)
{
scanf("%d %d %d %d",&x,&y,&z,&k);
add(x,y,z,k);
}
dij();
}
return 0;
}
·
·
Friends number
NBUT - 1223
题意
给你一个范围【a,b】,找出【a,b】之间有多找对朋友数。
朋友数的定义:假设x,y是一对朋友数,那么x的所有因子和等于y,y的所有因子和等于x
思路
真是让我长见识的一道题。。。如此的暴力竟然不超时
因为a,b的范围是5000000,所以先预处理出来1~5000000之间所有数的因子和(竟然不超时。。)
然后再预处理出来1~5000000 之间所有的朋友对数,一共只有71对,然后输入a,b,直接在这71对之间查找就好了
通过这道题发现:初始化用init()函数比较费时间,当时把init()里的初始化放在主函数里就过了,放在外面就T了… … … 还有就是用int比用long long 快好多,long long跑了900多MS,int只用了400多MS
还有if(…&&…&&…)这样的表达式顺序还是挺重要的,顺序不对会超时
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int f[5000005];
int a[500],b[500];
int tot;
int main()
{
tot=0;
for(int i=1; i<=5000000; i++)
{
int t=i+i;
while(t<=5000000)
{
f[t]+=i;
t+=i;
}
}
for(int i=1; i<=5000000; i++)
{
int A=i,y=f[i];
if(y>A&&y<5000000&&A==f[y])
{
a[tot]=A;
b[tot]=y;
tot++;
}
}
int n,m;
while(~scanf("%d %d",&n,&m))
{
int ans=0;
for(int i=0; i<tot; i++)
{
if(a[i]>=n&&a[i]<=m&&b[i]>=n&&b[i]<=m)
ans++;
}
printf("%d\n",ans);
}
return 0;
}
·
·
G - NEW RDSP MODE I
NBUT - 1225
题意
有n个数,1—n先按照从小到大的顺序排好,然后m次操作,一次操作的完整过程是:
1)初始序列叫做序列1
2)把奇数位的数字拿出来形成序列2
3)把序列2放在序列1的后面
例如 1 2 3 4 5一次操作之后变成2 4 1 3 5
问你在经过m次操作之后的那个序列前X个数字是多少
思路
在纸上画一画就知道,偶数位置下一次出现的位置是x/2,奇数位置下一次出现的位置是n/2+(x+1)/2
看到这个题知道有循环节的存在,以为这个循环节会有规律然而没有啥规律,就是每次模拟暴力算出来它的循环节,然后把先X个位置逆推出来
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int F_T(int n)//算循环节
{
int p=1,ans=0;
while(1)
{
ans++;
if(p%2)
{
p=n/2+(p+1)/2;
}
else
{
p/=2;
}
if(p==1)
return ans;
}
}
int f(int x,int n,int m)//模拟逆推
{
int p=x;
for(int i=1;i<=m;i++)
{
if(p*2<=n)
p=p*2;
else
p=(p-n/2)*2-1;
}
return p;
}
int main()
{
int n,m,x;
while(~scanf("%d %d %d",&n,&m,&x))
{
int t=F_T(n);
for(int i=1;i<=x;i++)
{
printf("%d",f(i,n,m%t));
if(i==x)
printf("\n");
else
printf(" ");
}
}
return 0;
}
·
·
H - A Simple Triangle
NBUT - 1226
题意:
按照题意打印三角形
Sample Input
3
5
6
Sample Output
1 2 3 4 5
2 4 6 8
3 6 9
4 8
5
1 2 3 4 5 6
2 4 6 8 10
3 6 9 12
4 8 12
5 10
6
好狗啊这个题。。如果当前的数字大于9就输出一个空格,否则输出两个空格,每行最后一个数字没有空格。。。。。。wa在这个空格上wa了五发。。。(英语硬伤,读了无数遍题)
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
int T,n;
int flag=0;
scanf("%d",&T);
while(T--)
{
if(flag)
printf("\n");
flag=1;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n-i+1; j++)
{
if(j==n-i+1)
{
printf("%d\n",j*i);
}
else
{
if((i*j)>9)
printf("%d ",j*i);
else
printf("%d ",j*i);
}
}
}
}
return 0;
}
·
·
I - Binary to Decimal
NBUT - 1227
题意
给你一个二进制转化为十进制,数据范围int之内,没啥说的,直接模拟
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char a[10000];
int main()
{
while(~scanf("%s",a))
{
int len=strlen(a);
int sum=0;
for(int i=len-1,j=0;i>=0;i--,j++)
{
if(a[i]=='1')
sum+=(1<<j);
}
printf("%d\n",sum);
}
return 0;
}
·
·
J - Bored Three-God
NBUT - 1228
大数A+B
没啥说的,直接敲板子,他们说好像要判前导零,然而我也每判,直接就过了。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char e1[100005],h1[100005];
int e[100005],h[100005],g[100005];
int main()
{
while(~scanf("%s %s",e1,h1))
{
int a=strlen(e1);
int b=strlen(h1);
int l=a>b?a:b;
memset(e,0,sizeof(e));
memset(h,0,sizeof(h));
memset(g,0,sizeof(g));
for(int i=0;i<a;i++)
e[i]=e1[a-1-i]-'0';
for(int i=0;i<b;i++)
h[i]=h1[b-1-i]-'0';
int k=0;
for(int i=0;i<l;i++)
{
g[i]=(e[i]+h[i]+k)%10;
k=(e[i]+h[i]+k)/10;
}
if(k==1)
printf("1");
for(int i=l-1;i>=0;i--)
printf("%d",g[i]);
printf("\n");
}
return 0;
}
·
·
K - Socks
CodeForces - 731C
题意
Arseniy的妈妈给他搭配好了m天的袜子,可是有某些天的袜子颜色是不一样的,Arseniy不想穿颜色不一样的袜子,他有k个颜色的油漆,Arseniy可以把袜子染色,问你需要最少染色多少只袜子,使得Arseniy每天穿的袜子都是一个颜色的
输入:
第一行n,m,k分别代表Arseniy有n只袜子,m天,k个颜色的油漆
第二行n个数代表第i个袜子的颜色
接下来m行代表妈妈给Arseniy搭配的袜子,每行两个数,代表Arseniy今天穿的两只袜子是第几只袜子
思路
主要是题意太不好理解了。。。
用并查集把每天的袜子都集中的有限个集合中,查看每个集合里最多颜色的袜子,把其他的袜子染成这个颜色就可以了
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
int n,m,k,g,tot;
int w[200005],f[200005],vis[200005],c[200005],ma[200005];
vector<int>ve[200005];
struct node
{
int v,nex;
};
node e[400005];
void add(int u,int v)
{
e[tot].v=v;
e[tot].nex=f[u];
f[u]=tot++;
}
void dfs(int u)
{
vis[u]=1;//把袜子放在第g个集合里
ve[g].push_back(u);
for(int i=f[u]; i!=-1; i=e[i].nex)
{
int v=e[i].v;
if(!vis[v])
dfs(v);
}
}
int main()
{
int x,y;
memset(f,-1,sizeof(f));
scanf("%d %d %d",&n,&m,&k);
for(int i=1; i<=n; i++)
scanf("%d",&w[i]);
for(int i=1; i<=m; i++)
{
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=1; i<=n; i++)
{
if(!vis[i])
{
g++;
dfs(i);
}
}
int ans=0;
for(int i=1;i<=g;i++)
{
int len=ve[i].size();
int sum=0;
for(int j=0;j<len;j++)
{
int v=ve[i][j];
ma[w[v]]++;//这里用map也是可以的,清空clear...当时还没学会map清空,用了数组模拟
if(sum<ma[w[v]])
sum=ma[w[v]];
}
ans+=(len-sum);
for(int j=0;j<len;j++)//用memset好像会T
{
int v=ve[i][j];
ma[w[v]]--;
}
}
printf("%d\n",ans);
return 0;
}
·
·
L - Wow! Such Conquering!
HDU - 4848
大概题意
一共有n个星球,给出你两两星球之间要达到的距离,每个星球有一个最晚到达的时间期限,问你从第一个星球开始,在每个星球最晚到达时间期限之内,到达每个星球的时间和是多少,如果到不了输出-1。
解
先用最短路跑出来两两星球到达的最小时间是多少,然后开始爆搜。。。。直接搜的话肯定超时,所以要加上剪枝。。。。
根据我的代码:time是到达u点所需要的时间,alltime是当前的总时间。
1)因为要算的是时间和,所以在深搜里,比如:(经过a点到到a+1,a+2…n点的时间都要加上1-a的时间,也就是(n-a)*time),如果alltime是搜到a点时之前的总时间,a点之后必须要有时间是(n-a)*time,所以alltime+(n-a)*time>sum的话,就没有搜下去的必要的,一定会超过现在的最优时间。
2)因为每个星球都有一个最后的时间期限,那么如果超过这个时间期限的话,就一定要剪枝。(这个具体看代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int e[45][45],n,ti[45];
int vis[45];
int sum;
void floyd()//求两两星球的最短时间
{
for(int k=0; k<n; k++)
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
if(e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
}
}
void dfs(int cnt,int time,int alltime,int u)//time是当前到达u的时间,alltime是到达u时所有的总时间
{
if(cnt==n)//搜到了n个点,取最优简化
{
sum=min(sum,alltime);
return;
}
if(alltime+(n-cnt)*time>=sum)//剪枝
return ;
for(int i=1;i<n;i++)//剪枝
{
if(!vis[i])
{
if(time+e[u][i]>ti[i])//如果i点还未到达,time是1-u的所需时间,
//通过u到达i的时间超过了i的最后期限,就没有必要搜下去了。
return ;
}
}
for(int i=1;i<n;i++)
{
if(!vis[i])
{
vis[i]=1;
dfs(cnt+1,time+e[u][i],alltime+time+e[u][i],i);
vis[i]=0;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
scanf("%d",&e[i][j]);
for(int i=1;i<n;i++)
scanf("%d",&ti[i]);
floyd();
sum=0x3f3f3f3f;
vis[0]=1;
dfs(1,0,0,0);
if(sum<0x3f3f3f3f)
printf("%d\n",sum);
else
printf("-1\n");
}
return 0;
}
·
·
M - Lisp em
SCU - 4490
题意:
输入两行单词,问你第一个相同的单词是哪个,没有输出No
用map模拟一下就好了
比赛的时候忘记string可以直接比较,被自己蠢到。。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<iostream>
using namespace std;
int main()
{
int T;
string a;
scanf("%d",&T);
while(T--)
{
map<string,int>ma;
while(1)
{
cin>>a;
if(a[0]=='n'&&a[1]=='i'&&a[2]=='l')
break;
ma[a]=1;
}
string b;
string c="0xffffff";
int flag=0;
while(1)
{
cin>>a;
if(a[0]=='n'&&a[1]=='i'&&a[2]=='l')
break;
if(ma[a]&&!flag)
{
flag=1;
b=a;
}
}
if(!flag)
printf("No\n");
else
{
printf("Yes ");
cout<<b;
printf("\n");
}
}
return 0;
}
·
·
N - Ultra-QuickSort
POJ - 2299
题意:
给出长度为n的序列,每次只能交换相邻的两个元素,问至少要交换几次才使得该序列为递增序列。
解
比赛的时候知道是归并排序但是很懵逼的是,时间不够。。。(只差了两分钟的我)
要使得序列从小到大排序,那么大的数要换到后面去,所以,我们只需要求当前数字后面有几个比它小的数,每个数都求一下,和就是答案
例如:
9 1 0 5 4
9 后面比它小的有 1 0 4 5 (4个)
1 后面比它小的有 0 (1个)
0 后面没有比它小的 (0个)
5 后面比它小的有 4 (1个)
4 后面没有比它小的 (0个)
所以4+1+1=6次;
交换的次数等于序列中的逆序对数
#include <stdio.h>
#include <algorithm>
int a[500000];
int d[500000];
unsigned long long count;
void mergeArray(int first, int mid, int last)
{
int i = first, j = mid+1, k =0;
int m = mid, n = last;
while(i<=m && j<=n){
if (a[i] <= a[j]) {
d[k++] = a[i++];
}
else {
d[k++] = a[j++];
count += m-i+1; //记录
}
}
while(i<=m) d[k++] = a[i++];
while(j<=n) d[k++] = a[j++];
for (int i=0;i<k; ++i) a[first+i] = d[i];
}
void mergeSort( int first, int end)
{
if (first < end)
{
int mid = (first + end)/2;
mergeSort(first, mid);
mergeSort(mid+1, end);
mergeArray(first, mid, end);
}
}
int main()
{
int num;
while (true)
{
scanf("%d", &num);
if (num <= 0) break;
for (int i=0; i<num; ++i) scanf("%d", &a[i]);
count = 0;
mergeSort( 0, num-1);//归并排序
printf("%lld\n", count);
}
return 0;
}
·
·
O - Pie
POJ - 3122
题意:
一共有n个味道的披萨,一共有f个朋友还有自己(也就是一共f+1个人),每个人都想要一样多的披萨,问每个人可以得到的最大的披萨体积是多少,不同味道的披萨不能给一个人
很经典的一个二分,及得好像做过,只是时间真的不够了。。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
int n;
int f;
double e[10000];
double pi=acos(-1.0);
int F(double mid)
{
int ans=0;
for(int i=1;i<=n;i++)
{
ans+=(int)(e[i]/mid);
}
if(ans>=(f+1))
return 1;
else
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&f);
for(int i=1;i<=n;i++)
{
scanf("%lf",&e[i]);
e[i]=e[i]*e[i]*pi;
}
sort(e+1,e+1+n);
double l=0.0,r=e[n],ans;
while(r-l>0.00001)
{
double mid=(l+r)/2;
if(F(mid))
{
ans=mid;
l=mid;
}
else
r=mid;
}
printf("%.4f\n",ans);
}
return 0;
}
·
·
P - 无剑无我
HDU - 2547
题意
定义 f(x, y, m, n) = sqrt(xx + yy + mm + nn - 2mx - 2ny);
(其中x,y为位置变量,m,n为属性常量)
F = f(x, y, a, b) + f(x, y, c, d);
F的最小值
当时随便瞎搞了一下,感觉就是让一个为0 ,竟然过了,下来之后发现这就是两点之间距离公式,宛如一个智障。。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
int main()
{
double a,b,c,d;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lf %lf %lf %lf",&a,&b,&c,&d);
double x=a;
double y=b;
double ans=sqrt((x-a)*(x-a)+(y-b)*(y-b))+sqrt((x-c)*(x-c)+(y-d)*(y-d));
x=c;
y=d;
double sum=sqrt((x-a)*(x-a)+(y-b)*(y-b))+sqrt((x-c)*(x-c)+(y-d)*(y-d));
printf("%.1f\n",ans<sum?ans:sum);
}
return 0;
}
·
·
Q - 水陆距离
HihoCoder - 1478
给定一个N x M的01矩阵,其中1表示陆地,0表示水域。对于每一个位置,求出它距离最近的水域的距离是多少。
矩阵中每个位置与它上下左右相邻的格子距离为1。
思路
就是把水域放进去,然后所有的水域一起搜,先到的一定是最短的
当时想起来了搜水域,没有想到同时搜。。。。哇。。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int n,m;
char mapp[805][805];
int vis[805][805],e[805][805];
int nex[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
struct node
{
int x,y,bu;
};
queue<node>q;
void dfs()
{
node a;
while(!q.empty())
{
a=q.front();
q.pop();
int xx=a.x;
int yy=a.y;
int bushu=a.bu;
for(int i=0;i<4;i++)
{
int tx=xx+nex[i][0];
int ty=yy+nex[i][1];
if(vis[tx][ty])
continue;
if(tx<0||tx>=n||ty<0||ty>=m)
continue;
e[tx][ty]=bushu+1;
vis[tx][ty]=1;
node b;
b.x=tx;
b.y=ty;
b.bu=bushu+1;
q.push(b);
}
}
}
int main()
{
node a;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%s",mapp[i]);
for(int j=0;j<m;j++)
{
if(mapp[i][j]=='0')
{
vis[i][j]=1;
a.x=i;
a.y=j;
a.bu=0;
q.push(a);
e[i][j]=0;
}
}
}
dfs();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
printf("%d%c",e[i][j],j==m-1?'\n':' ');
}
}
return 0;
}`