现在的位置: 首页 > 综合 > 正文

22/7/2012 ICPC培训 第七天

2013年09月21日 ⁄ 综合 ⁄ 共 2843字 ⁄ 字号 评论关闭

又来吐糟了啦。。。

今天照样刷出来的题不多大哭。勉强也只能算个三题半吧!

 

上午在做上次比赛的B题。

要用数据结构,vector和deque。也第一次感受到了数据结构的魅力,的确把时间复杂度优化的很好。

按照出题者的思路写出了代码,TLE了。结果你懂得,各种纠结,再也想不到如何优化了。。。

然后,就在刚才,把出题人-—唐爽童鞋的代码拿来,居然也TLE了惊恐。神马情况。

 

快到中午,眼看没A题。唉,退而求其次,A一水题吧。

HDU2289,求圆台的高。

主要就是根据性质求出高和半径的关系。然后根据圆台体积公式得到体积和高的关系。最后就是二分

解方程了。坑爹的是这题要求的精度很高、pi不取好也很难A。。。

代码:

#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;

const double pi=3.1415926535897931;
const double accurate=1e-7;

double r,R,H,V,h;

double calculate(double x)
{
    return pi*x*(r*r+pow(r+(R-r)/H*x,2)+r*(r+(R-r)/H*x))/3.0;
}

void binSearch(double low,double high)
{
    double mid=(low+high)*1.0/2.0;
    
    if(high-low<=accurate)  //这句没加,超时了几次,二分查找对出口一定得判断好 
    {                       //但理论上我认为这是不对的,根本就没有逼近V,只是 
        h=mid;              //递归的出口,否则超时 
        return;
    }
    
    if(fabs(calculate(mid)-V)<=accurate)
    {
        h=mid;
        return;
    }
    else if(calculate(mid)>V)
    {
        binSearch(low,mid);
    }
    else
    {
        binSearch(mid,high);
    }
}

int main()
{
    int cas;
    
    cin>>cas;
    
    while(cas--)
    {
        cin>>r>>R>>H>>V;
        
        binSearch(0,H);
        
        cout<<setiosflags(ios::fixed)<<setprecision(6)<<h<<endl;
    }
    
    return 0;
}

 

下午刷了HDU4301。

用DP来做,其实我是看解题报告才懂得!

上次比赛,居然还搞3*n!!!果断做不出来。

我就不啰嗦了,不懂可直接看解题报告:点击打开链接

代码:

//dp[i][0][j]表示前i行分成j部分且第i行的两块属于同一部分
//dp[i][1][j]表示前i行分成j部分且第i行的两块属于不同部分           
#include<iostream>
#include<cstring>
using namespace std;

const int MAX=1010;
const int MOD=100000007;

__int64 dp[MAX][2][MAX*2];
int n,k;

void DP()
{
    memset(dp,0,sizeof(dp));
    
    dp[1][0][1]=dp[1][1][2]=1;  //初值 
    
    for(int i=1;i<=999;i++)
    {
        for(int j=1;j<=2000;j++)
        {
            //状态转移方程 
            dp[i+1][0][j]=(dp[i+1][0][j]+dp[i][0][j]+dp[i][1][j]*2)%MOD;
            dp[i+1][1][j]=(dp[i+1][1][j]+dp[i][1][j])%MOD;
            dp[i+1][0][j+1]=(dp[i+1][0][j+1]+dp[i][0][j]+dp[i][1][j])%MOD; 
            dp[i+1][1][j+1]=(dp[i+1][1][j+1]+dp[i][0][j]*2+dp[i][1][j]*2)%MOD;
            dp[i+1][1][j+2]=(dp[i+1][1][j+2]+dp[i][0][j]+dp[i][1][j])%MOD;
        }
    }
} 
            
int main()
{
    DP();
     
    int cas;
    
    cin>>cas;
    while(cas--)
    {
        cin>>n>>k;
        
        cout<<(dp[n][0][k]+dp[n][1][k])%MOD<<endl;
    }
    
    return 0;
} 

 

最后一题(HDU1969)

这还是一道二分题。

还是被卡了一会的。主要因为对递归还是不太明白。

这样的题比较好。它不像在一维数组内查找一个数是否存在,它要求不仅要求出结果,还要是最大或最小的。

当然,是在一定精度范围内。

另外就是,这两类二分题其实在代码上都是有规律可循的。刷两道题,总结下即可。

代码:

#include<iostream>
#include<algorithm> 
using namespace std;

const double pi=3.1415926535897931;
const double accurate=1e-5;
const int MAX=10000;
 
double volume[MAX],maxPiece; 
int numPie,numFriend; 

inline double calculate(double r)
{
    return pi*r*r;
}
 
void input()
{
    int radii;
     
    for(int i=0;i<numPie;i++)
    {
        scanf("%d",&radii);
        volume[i]=calculate(radii);
    }

    sort(volume,volume+numPie); 
}
 
int calculateNum(double v)
{
    int num=0;
    
    for(int i=0;i<numPie;i++)
    {
        num+=int(volume[i]/v);
        
        if(num>numFriend+1) break;
    }
    
    if(num>=numFriend+1)
    {
        maxPiece=maxPiece>v?maxPiece:v;
    }
     
    return num;
}
 
void binSearch(double low,double high)
{
    double mid=(low+high)/2;  
     
    if(high-low<=accurate)
    {
         //maxPiece=maxPiece>mid?maxPiece:mid;
         return;
    }
    
    if(calculateNum(mid)>=numFriend+1)
    {
        binSearch(mid,high);
    }
    else
    {
        binSearch(low,mid);
    } 
}
         
int main()
{
    int cas;
    
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&numPie,&numFriend);
        
        input();
        
        maxPiece=-1;
         
        binSearch(0,volume[numPie-1]);
        
        printf("%.4lf\n",maxPiece); 
     }
     
     return 0;
} 

 

最后,晚上张浩然同学给我们讲了下图论。最小生成树、最短路径、并查集、强连通分量。。。

各种算法,又有事干咯。

 

 

 

 

 

 

 

 

抱歉!评论已关闭.