水题
int m ;
bool vis[100];
int aa = 0 ;
int mm[50][50];
int dp[100];
void dfs(int now , int nn)
{
dp[nn] = now;
if(nn == 19)
{
if(mm[now][m])
{
cout <<aa<<": ";
for (int i = 0 ;i < 20 ;i ++)
cout <<" "<<dp[i];
cout <<" "<<m<<endl;
aa ++ ;
}
}
for (int i = 1 ;i <= 20 ;i ++)
if(mm[now][i])
{
if(!vis[i])
{
vis[i] = 1 ;
dfs(i, nn + 1 );
vis[i] = 0 ;
}
}
}
int main()
{
mem(mm,0);
for (int i = 1 ; i <= 20 ; i ++ )
{
int a ,b , c ;
cin >> a >> b >> c ;
mm[i][a] = 1 ;
mm[i][b] = 1 ;
mm[i][c] = 1 ;
}
while(scanf("%d",&m) ,m )
{
aa = 1 ;
mem(dp,0);
mem(vis,0);
vis[m] = 1 ;
dfs(m,0);
}
return 0;
}
1002
Red and Black
水题
bool vis[100][100];
char mm[100][100];
int n , m ;
int xx[4] = {0 ,0 ,1 ,-1};
int yy[4] = {1,-1,0,0};
int inmap(int x,int y )
{
if(x >= 0 &&x < m &&y >= 0 &&y < n)return 1;
return 0;
}
void dfs(int x ,int y )
{
for (int i = 0 ;i < 4 ; i ++)
{
int tx = x + xx[i];
int ty = y + yy[i];
if(inmap(tx,ty)&&!vis[tx][ty]&&mm[tx][ty] != '#')
{
vis[tx][ty] = 1 ;
dfs(tx,ty);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m) ,(m + n ))
{
mem(vis,0);
for (int i = 0 ;i < m ;i ++){
scanf("%s",mm[i]);
}
for (int i = 0 ;i < m ;i ++)
{
for (int j = 0 ;j < n ;j ++)
if(mm[i][j] == '@')
{
vis[i][j] = 1 ;
dfs(i,j);
break;
}
}
int ans = 0 ;
for (int i = 0 ;i < m ;i ++)
{
for (int j = 0 ;j < n ;j ++)
if(vis[i][j])
ans ++;
}
cout <<ans <<endl;
}
}
1003 Oil Deposits
水题
int n , m ;
char mm[105][105];
int xx[8] = {0,0,1,-1,1,1,-1,-1};
int yy[8] = {1,-1,0,0,1,-1,1,-1};
bool vis[105][105];
int inmap(int x,int y)
{
if(x >= 0 &&x < n &&y >= 0 &&y < m && mm[x][y] != '*')
return 1;
return 0;
}
void dfs(int x, int y )
{
for (int i = 0 ;i < 8 ;i ++)
{
int tx = x + xx[i];
int ty = y + yy[i];
if(inmap(tx,ty)&&!vis[tx][ty])
{
vis[tx][ty] = 1;
dfs(tx,ty);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m) , (n + m ))
{
for (int i = 0 ;i < n ;i ++)
scanf("%s",mm[i]);
int ans = 0 ;
mem(vis,0);
for (int i = 0 ;i < n ;i ++)
{
for (int j = 0 ;j < m; j ++)
{
if(mm[i][j] == '@' && !vis[i][j])
{
ans ++;
dfs(i,j);
}
}
}
cout <<ans <<endl;
}
}
1004 Can you solve this equation?
水题
double cal(double x)
{
double c = 8 * x * x * x * x + 7 * x * x * x + 2 * x * x + 3 * x + 6 ;
return c;
}
int main()
{
int T;
cin >> T;
while( T -- )
{
double x ;
cin >> x ;
if(x < cal(0.0) || x > cal(100.0))
{
printf("No solution!\n");
}
else
{
double low = 0 ,high = 100;
double mid = (low + high) / 2 ;
while(high - low > 1e-11)
{
mid = (high + low ) / 2 ;
double cc = cal(mid);
if(cc == x)
break;
if(cc < x)
low = mid ;
else high = mid ;
}
mid = (high + low) / 2 ;
printf("%.4f\n",mid);
}
}
}
1005
Selecting Problems
题意:就是给你一些人,每个人都能做一些题目,然后给出一个人数限制k,问至少有k个人都会做同样的题,问这个题数最大是多少。
思路:题目中给出的题目总数m <= 15,所以可以用二进制表示一个人会做那些题目。
可以先预处理出0 - 2^15 的题目作法 。
这里就发生了做这道题最悲剧的一件事,我直接把每道题扔进一个vector里,想也没想就开始二分了。
然后TLE。我就开始改二分的条件,想着估计是哪个状态没跳出,在mid 那里处理的不好。所以就开始了我的狂T之旅。
贴上vector的预处理。
for (int i = 0 ;i < 1<<15 ; i ++)
{
int num = i ;
int ans = 0 ;
while( num )
{
if(num & 1 ) ans ++;
num /= 2;
}
qq[ans].push_back(i);
}
好不容易想到把vector改成数组好了。
for (int i = 0 ; i < 1<<15 ; i ++)
{
int num = i ;
int ans = 0 ;
while( num )
{
if(num & 1 ) ans ++;
num /= 2;
}
qq[ans][f[ans] ++] = i ;
}
然而悲剧的事情还没结束。
因为还是T。。。然后我又陷入了狂改mid值的过程当中。。。期间T了无数次。
然后不知道啥想法,我就把交代码的语言改成GUN C ++ .(我这边一直默认是交Visual C++)。。
然后就A了。。。
A了。。。
了。。。
PS:亲测换了语言后如果用vector也是T 。今天你被坑了吗?
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2005
#define inf 1<<28
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define FOR(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
using namespace std;
string st;
int q[1005];
int n , m , k, ans ;
bool vis[1005];
int qq[20][1<<16];
char ddd[25];
int f[20];
int main()
{
//mem(f,0);
//mem(qq,0);
for (int i = 0 ; i <= 1<<15 ; i ++)
{
int num = i ;
int ans = 0 ;
while( num )
{
if(num & 1 ) ans ++;
num /= 2;
}
qq[ans][f[ans] ++] = i ;
}
while(scanf("%d%d%d",&n,&m,&k) != EOF)
{
mem(q,0);
ans=0;
for (int i = 0 ; i < n ; i ++)
{
int a ;
scanf("%s",ddd);
scanf("%d",&a);
while(a -- )
{
int x ;
scanf("%d",&x);
x --;
q[i] |= 1 << x;
}
}
int low = 0 ,high = m ;
while(high >= low)
{
int mid = (high + low) / 2 ;
int num ;
int l = f[mid];
for (int i = 0 ; i < l; i ++)
{
num = 0 ;
for (int j = 0 ; j < n ; j ++)
{
if((q[j] & qq[mid][i]) == qq[mid][i])
num ++;
}
if(num >= k)
{
ans = mid ;
low = mid + 1 ;
break;
}
}
if(low <= mid) high = mid - 1 ;
}
printf("%d\n",ans);
}
return 0;
}
1006 Dwarven Sniper’s hunting
最长距离肯定是子弹的最大射击距离,二分时间,找出最短的时间可以射击到敌人。
double xx1,yy1,xx2,yy2,lx,ly,vd,vb,l;
int main()
{
while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf",&xx1,&yy1,&xx2,&yy2,&lx,&ly,&vd,&vb,&l))
{
if(xx1 == 0 && xx2 == 0 && yy1 == 0 && yy2 == 0 && lx == 0 && ly ==0 && vd == 0 && vb == 0 && l ==0 )
return 0;
double ftime = (double)l / (double)vb ;//子弹飞的时间
double left = ftime ,right = 1e7;
double mid = (left + right ) / 2 ;
while(right - left > 1e-11)
{
mid = (left + right ) / 2 ;
double nowx = xx1 + lx * mid ;//敌人当前位置
double nowy = yy1 + ly * mid ;
double dis = sqrt((xx2 - nowx) * (xx2 - nowx ) + (yy2 - nowy ) * (yy2 - nowy));//俩人的距离
double dis1 = (mid - ftime) * vd ;//需要跑的距离
if(dis1 >= fabs(dis - l))
right = mid ;
else
left = mid ;
}
mid = (left + right ) / 2;
printf("%.3f %.3f\n",l,mid);
}
}
1007 Dome of Circus
三分圆锥的高,求出体积的最小值。记录高和半径。
double a[Max],b[Max],c[Max];
int main()
{
int T ;
cin >> T;
while ( T -- )
{
int n ;
cin >> n ;
for(int i = 0 ; i < n ; i ++)scanf("%lf%lf%lf",a + i ,b + i ,c + i );
double l = 0 , r = 10000 ;
double h = inf , rr = inf;
double ansarea = inf;
while(r - l > 1e-11)
{
double mid = (l + r ) / 2;
double midd = (r + mid ) / 2 ;
double mr = 0 ;
double mmr = 0;
for (int i = 0 ; i < n ; i ++)
{
double mm = sqrt(a[i] * a[i] + b[i] * b[i])* mid / (mid - c[i]);//根据比例关系,求出底面半径
double mmm = sqrt(a[i] * a[i] + b[i] * b[i])* midd / (midd - c[i]);
if(mr < mm) mr = mm ;//更新半径的最大值
if(mmr < mmm )mmr = mmm;
}
double ansmid = mr * mr * PI * mid / 3 ;
double ansmidd = mmr * mmr * PI * midd / 3 ;
if(ansarea > ansmid)
{
ansarea = ansmid;
h = mid;
rr = mr;
}
if(ansarea > ansmidd)
{
ansarea = ansmidd ;
h = midd;
rr =mmr ;
}
if(ansmid > ansmidd)
{
l = mid ;
}
else
{
r = midd;
}
}
printf("%.3f %.3f\n",h,rr);
}
}
1008
Turn the corner
三分角度,求出最大的过弯y,最后比较判断。
一开始很sb的直接把角度带进三角函数里计算。。。忘了化成pi
double cal(double n ,double x ,double l ,double d)
{
double xx,yy,c,s;
s = sin(n);
c = cos(n);
xx = -1 * (d / s + c * l) ;
yy = ( d / c + s * l ) ;
double tmp = ( 1.0 - x / yy ) * xx * (-1);
return tmp;
}
int main()
{
double l ,d , x , y ;
while(cin >> x >> y >> l >> d)
{
double low = 0 , high = 90.0 ;
double ans = 0 ;
while( high - low > 1e-8)
{
double mid = (low + high) / 2 ;
double midd = (low + mid ) / 2 ;
double amid = cal(mid * PI / 180,x,l,d);
double amidd = cal(midd * PI / 180,x,l,d);
ans = max(ans,max(amid,amidd));
if(amid > amidd)
{
low = midd;
}
else
high = mid ;
}
if(ans > y)
cout <<"no"<<endl;
else
cout <<"yes"<<endl;
}
}
1009 Error Curves
题意:给出一堆二次函数,然后求出他们组成的最大值的最小值。。有点拗口。
想一下图形就知道了 。
红色部分是两个二次函数的最大部分,然后最下面那个点就是最小值。所以同样可以用三分求解。
double a[Max],b[Max],c[Max];
double cal(double aa,double bb ,double cc,double xx)
{
double dd = aa * xx * xx + bb * xx + cc;
return dd;
}
int main()
{
int T ;
cin >> T ;
while( T -- )
{
int n ;
cin >> n ;
for (int i = 0 ;i < n ;i ++ )
scanf("%lf%lf%lf",a + i ,b + i ,c + i);
double l = 0 ;
double r = 1000.0;
double mid = (l + r) / 2 ;
double ansy = inf;
while( r - l > 1e-11)
{
mid = (l + r ) / 2 ;
double midmid = (mid + r ) / 2 ;
double ansmid = -inf ;//一开始这个初值赋成0。。然后就又悲剧了,太粗心了。
double ansmidmid = -inf ;
for (int i = 0 ; i < n ;i ++)
{
double mm = cal(a[i],b[i],c[i],mid);
double mmm = cal(a[i],b[i],c[i],midmid);
if(ansmid < mm)ansmid = mm;
if(ansmidmid < mmm) ansmidmid = mmm;
}
ansy = min(ansy,min(ansmid,ansmidmid));
if(ansmid > ansmidmid)
l = mid;
else
r = midmid;
}
printf("%.4f\n",ansy);
}
}
1010
湫湫系列故事——设计风景线
接下来介绍这道传说中的坑王之王。
这道题是腾讯马拉松的题,那天比赛的时候我还和学长讨论了一下。问题就集中在这个最长路径,他和我说就是最长路,我说可以是树啊。这个最长路径当时就很迷茫了。赛后去看了 解题报告,写的都是水并查集,然后求最大生成树,然后找出最大值。
当时我就在YY,早知道我就写这道题了。。。(因为题意不明确,当时我就去做1002了,赛后发现是神题。。。)
好了,回到这次比赛的这道题。。
又一次看到这道题,我想都没想直接并查集敲上去,10分钟不到就交了。然后就WA了。。之后改改交交WA了5, 6次之后。。我就觉得不对了。。
我已经完全可以证明我的思路是正确的了。
然后我就出去找到了原题HDU4514 。才发现DISCUSS里面说题意已经改了。。。改成求最长路了。。。
当时我就被雷的里焦外嫩,果然是神坑。
然后就开始重新写了 。
1.判环,我就没改,直接并查集,物尽其用了。
2.找最长路,这部分我一开始用spfa,但是敲着敲着就跑不出来了。。
3.然后我就发现一种很神的办法,就是求树的直径。
树上的最长路就是树的直径。然后可以用两遍BFS解决。
先在这颗树里随意找一点进行BFS,找出最长路的那个节点。
然后对这个节点进行一次BFS,找出的最长路即为这棵树的最长路,也就是直径。
算法正确性证明见:http://blog.sina.com.cn/s/blog_77dc9e0801015m8z.html
4.这道题让我跪了N次的地方,就是我发现居然会MLE。。。
5.然后我就开始各种改数组,还是MLE,只好将判环的并查集改了,将那几个数组都去了。然后用DFS进行判环。
6.这次没MLE了,但是栈溢出了。加了个外挂。然后还是溢出。
7.这次和1005那题是一样的坑,我随手换了个语言Visual C++ 就A了(因为做完1005我就把默认语言改成GUN C++了,而用这个交一直爆栈)。。
这就是这道题的集锦。。下面贴代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 10001
#define inf 1<<28
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define FOR(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#pragma comment(linker, "/STACK:10240000000000,10240000000000")
using namespace std;
struct kdq
{
int e ,l ,next;
} ed[Max * 200];
int head[Max * 10] ;
int num ;
int vis[Max * 10] ;
int dis[Max * 10] ;
int ans = 0 ;
void add(int s,int v ,int l)
{
ed[num].e = v ;
ed[num].l = l ;
ed[num].next = head[s];
head[s] = num ++ ;
}
void init()
{
mem(head,-1);
num = 0 ;
mem(dis,0);
ans = 0 ;
}
int dfs(int now ,int pre)
{
vis[now] = 1 ;
for (int i = head[now ]; i != -1 ; i = ed[i].next)
{
int v = ed[i].e ;
if(v != pre)
{
if(vis[v])
return 0 ;
if(dfs(v ,now) == 0)
return 0;
}
}
return 1 ;
}
bool vis1[Max * 10] ;
void bfs(int now )
{
mem(vis1,0);
vis1[now] = 1 ;
dis[now] = 0 ;
queue<int>qe;
qe.push(now);//任选一个节点进行BFS
//qe[0] = now ;
int v = now ;
int vv = dis[now] ;
while(!qe.empty())
{
int tt = qe.front();
//int tt = qe[l ++ ];
qe.pop();
for (int i = head[tt] ; i != -1 ; i = ed[i].next)
{
int t = ed[i].e ;
int tl = ed[i].l ;
if(!vis1[t])
{
dis[t] = dis[tt] + tl ;
vis1[t] = 1 ;
if(vv < dis[t]) vv = dis[t] , v = t ;//找出最长路的节点
//qe[r ++ ] = t ;
qe.push(t) ;
}
}
}
//if(ans < vv) ans = vv ;
//mem(vis,0);
while(!qe.empty())qe.pop();
qe.push(v);//对这个节点再进行一次BFS
vis[v] = 1;
dis[v] = 0 ;
while(!qe.empty())
{
int tt = qe.front() ;
qe.pop() ;
for (int i = head[tt] ; i != -1 ; i = ed[i].next)
{
int t = ed[i].e ;
int tl = ed[i].l ;
if(!vis[t])
{
dis[t] = dis[tt] + tl ;
vis[t] = 1 ;
if(ans < dis[t])ans = dis[t] ;
qe.push(t) ;
}
}
}
}
int main()
{
int n , m ;
while(scanf("%d%d",&n,&m) != EOF)
{
//for (int i = 0 ; i <= n ; i ++)f[i] = i ;
init();
for (int i = 0 ; i < m ; i ++)
{
int a , b, c ;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c) ;
add(b,a,c) ;
}
bool flag = 0;
mem(vis,0);
for (int i = 1; i <= n ; i ++)
if(!vis[i])
{
if(dfs(i , -1 ) == 0)//dfs判环
{
flag = 1 ;
break;
}
}
if(flag)
{
cout <<"YES"<<endl;
continue;
}
mem(vis,0) ;
int k ;
for (int i = 1 ; i <= n ; i ++)
{
if(!vis[i])
{
bfs(i);
}
}
printf("%d\n",ans);
}
}
/*
4 3
1 2 1
2 3 1
3 4 1
*/