二分搜索题

定义:对于一个非负整数组成的序列,如果存在一个无向图的度序列和其一致,则该序列是可图的。

Havel-Hakimi定理:给定一个非负整数序列{d1,d2,...dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。

由非负整数组成的有限非递增序列,S={d1,d2,d3...dn},当且仅当S1={d2-1,d3-1...d(d1+1)-1,d(d1+2),d(d1+3),......dn}也是可图的

三题的解释都写注释里面了,懒得分开写,感觉写注释里清楚一点。
poj1659

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std; 
const int N=15;
typedef struct hu{
    int id;
    int nu;
}hu;
hu num[N];
int t;
bool guan[N][N];
bool cmp(hu a,hu b){
    return a.nu>b.nu;
}
bool f(int k)//k cur
{
    sort(num+k,num+t+1,cmp);
    if(num[t].nu<0)return 0;
    if(k==t)return 1;
    for(int i=k+1;i<=k+num[k].nu;i++)
    {
        num[i].nu--;
        guan[num[i].id][num[k].id]=guan[num[k].id][num[i].id]=1;
    }
    f(k+1);
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        cin>>t;
        for(int i=1;i<=t;i++)
        {
            cin>>num[i].nu;
            num[i].id=i;
        }
        memset(guan,0,sizeof(guan));
        if(f(1))
        {
            cout<<"YES"<<endl;
            for(int i=1;i<=t;i++)
            {
                for(int j=1;j<=t;j++)
                {
                    cout<<guan[i][j]<<' ';
                }
                cout<<endl;
            }

    cout<<endl;
        }
        else cout<<"NO"<<endl<<endl;
    }
}

poj2018

#include<iostream>
#define max(x,y) (x>y)?(x):(y)
#define min(x,y) (x<y)?(x):(y)
using namespace std;
const int N=100005;
double a[N];
double sum[N];
double d[N];
double sumd[N];
int main()
{
    int n,f;
    cin>>n>>f;
    double maxx=0,minn=1e8;
    sum[0]=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        maxx=max(maxx,a[i]);//取区间最大值 
        minn=min(minn,a[i]);//取区间最小值 
    }
    int count=0;
    while(maxx-minn>1e-4)//二分,精度题目中限定了三位小数 
    {
        double mid=(maxx+minn)/2; 
        double maxxx=-1e8;
        double minnn=1e8;
        for(int i=1;i<=n;i++)
        {
            d[i]=a[i]-mid;//每个数减去当前的均值,很好的一个技巧,把对均值的增加减少的贡献,化为正负好判断
            sumd[i]=sumd[i-1]+d[i];//前缀和 
        }
        for(int i=f;i<=n;i++)//dp 
        {
            minnn=min(minnn,sumd[i-f]); 
            maxxx=max(maxxx,sumd[i]-minnn);
        }
        if(maxxx>=0)minn=mid;
        else maxx=mid;
    }
    cout<<int(maxx*1000)<<endl;
}

codeforces1073c

#include<iostream>
#include<string.h>
#include<string>
using namespace std;
#define abs(x) ((x>=0)?(x):(-x))
const int N=200005;
const int INF=0x3f3f3f3f;
int x[N];
int y[N];
int endx,endy;
int n;
bool check(int m)
{
    for(int i=1;i+m-1<=n;i++){
        int xx=x[n]-x[i+m-1]+x[i-1];
        int yy=y[n]-y[i+m-1]+y[i-1];
        //从i到i+m-1删去,即整个序列[1,i-1]+[m,n]的和  
        //tx ty是要修改的区间修改后应该对应的x和y
        int tx=endx-xx;
        int ty=endy-yy;
        //二者的差值 
        //区间长m>=|tx|+|ty|而且m与|tx|+|ty|同奇偶,剩下的两两相消
        if(abs(tx)+abs(ty)<=m &&(m-abs(tx)-abs(ty))%2==0)return true;
    }
    return false;
}
int main()
{
    string s;
    while(cin>>n){
    cin>>s;
    cin>>endx>>endy;
    memset(x,0,sizeof(x));
    memset(y,0,sizeof(y));
    
    for(int i=1;i<=s.length();i++)
    {
        switch(s[i-1])
        {
            case 'U':
                x[i]=x[i-1];
                y[i]=y[i-1]+1;
                break;
            case 'D':
                x[i]=x[i-1];
                y[i]=y[i-1]-1;
                break;
            case 'L':
                y[i]=y[i-1];
                x[i]=x[i-1]-1;
                break;
            case 'R':
                y[i]=y[i-1];
                x[i]=x[i-1]+1;
                break;
        }
    }
    //二分 区间长度 
    int l=0,r=n;
    int mid,ans=INF;     
    while(l<=r){
        mid=(l+r)>>1;
        if(check(mid)){
            r=mid-1;
            ans=mid;
        }
        else
        {
            l=mid+1;
        }
    }
    if(ans==INF)
    {
        cout<<"-1"<<endl;
    }
    else
    {
        cout<<ans<<endl;
    }
    }
}
 

猜你喜欢

转载自blog.csdn.net/baidu_39394563/article/details/83823654
今日推荐