Codeforces Round#321 (div.2) A,B,C,D;(细节处理,尺取,dfs(树上的),状态压缩dp)

来源:互联网 发布:程序员的自我修养 ppt 编辑:程序博客网 时间:2024/06/05 18:15

附上大神链接:http://www.cnblogs.com/alihenaixiao/p/4836471.html#3276283      自己写的A,C,借鉴的大神的B,D;

这个我的头文件习惯了写将近40行,所以就写这了,下面就不写了啊;

#include<iostream>
#include<sstream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<list>
#include<stack>
#include<map>
#include<set>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>


using namespace std;


#define rep(a,b,c) for(int a=b;a<=c;a++)
#define drep(a,b,c) for(int a=b;a>=c;a--)
#define mkp make_pair
#define pub push_back
#define pob pop_back


typedef long long ll;
typedef long double lb;
typedef pair<int,int> pii;


const int maxn = 100000+10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const int dx[8]={0,0,1,-1,1,1,-1,-1};
const int dy[8]={1,-1,0,0,1,-1,1,-1};


580A:

题目大意:

求一个非下降子串,然后就是细节处理,我觉得我这么写还是挺好的,挺清楚的,以后都这么写了;

基本思路:

就算不比较,让自己也是一个,所以最短也是1吧,然后这样的话很自然想到从idex=2开始比较,然后就特别对待一下idex=n的情况,不然可能都跳出循环了,还没有把值赋给res;

代码如下:

int arr[maxn];


int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
    int maxx=1;
    int cnt=1;
    for(int i=2;i<=n;i++)
    {
        if(arr[i]>=arr[i-1]) cnt++;
        else
        {
            if(cnt>maxx) maxx=cnt;
            cnt=1;
        }
        if(i==n)
        {
            if(cnt>maxx) maxx=cnt;
        }
    }
    printf("%d\n",maxx);
}


580B:

题目大意:

一群人去参加庆祝趴,每个人都有两个属性(身价,贡献),在庆祝趴里面身价最大的和身价最小的差值不能大于等于d,问庆祝趴内所有人的总贡献最大为多少?

基本思路:

首先你选那么一堆人,这一堆人里面最大和最小身价的差值肯定是小于等于d,然后这很自然让人想到先排个序吧,然后就是尺取法了吧;

代码如下:

struct Node
{
    ll m,s;
    bool operator<(const Node& a)const
    {
        return m<a.m;
    }
}node[maxn];




int main()
{
    ios::sync_with_stdio(false);
    int n,d;
    cin>>n>>d;
    node[0].m=node[0].s=0;
    rep(i,1,n) cin>>node[i].m>>node[i].s;
    sort(node+1,node+n+1);
    rep(i,1,n) node[i].s+=node[i-1].s;
    ll mx=node[1].s;
    int left=1;
    rep(i,2,n)
    {
        while(node[i].m-node[left].m>=d&&left<i)
            left++;
        mx=max(mx,node[i].s-node[left-1].s);
    }
    cout<<mx<<endl;
}


580C:

题目大意:

有一个树,1节点是home,叶子节点是公园,在节点中可能会有猫,问从home出发在路上不能经过连续的m个猫,问能到达几个不同的公园?

基本思路:

树上的dfs就好了,然后注意弄一下叶子结点,然后就没啥了,偶,对了,用了一下邻接表,这玩意太好使了,而且比用vector快很多,(其实后自己是能做出来的,有想法的,但总是不敢去做,这很不应该,一起不是就喜欢做难题来着吗?将这种品质拾起来);

代码如下:

int n,m,res,pos;
int arr[maxn],du[maxn];
struct Node
{
    int to,next;
}node[maxn*2];
int head[maxn];


void AddEdge(int u,int v)
{
    node[pos].to=v;
    node[pos].next=head[u];
    head[u]=pos++;
}


void dfs(int s,int f,int cnt)
{
    for(int i=head[s];i!=-1;i=node[i].next)
    {
        int t=node[i].to;
        if(t!=f)
        {
            if(arr[t])
            {
                if(cnt+1>m) continue;
                else dfs(t,s,cnt+1);
            }
            else dfs(t,s,0);
        }
    }
    if(du[s]==1&&s!=1) res++;
}


int main()
{
    ios::sync_with_stdio(false);
    memset(head,-1,sizeof(head));
    memset(du,0,sizeof(du));
    pos=res=0;
    cin>>n>>m;
    rep(i,1,n) cin>>arr[i];
    int u,v;
    rep(i,1,n-1)
    {
        cin>>u>>v;
        du[u]++;
        du[v]++;
        AddEdge(u,v);
        AddEdge(v,u);
    }
    if(arr[1]) dfs(1,0,1);
    else dfs(1,0,0);
    cout<<res<<endl;
}


580D:

题目大意:

以后碰到类似的选哪些的题目,应该自然就会想到状态压缩dp了,然后这个dp的状态要怎么定义呢,因为加分像必须是吃完第一个接着吃第二个才能加分,所以这样的话设置一个二维的,然后第一维就是状态,第二维就是最后吃的那一道菜是哪一道,然后就能写出这个程序了(即使这样我也想不出来啊,不过做完这个题之后我觉得以后遇到类似的我一定能想出来,主要就是&一下看idex=j这道菜是不是在里面,就是是不是吃过,然后k这里这个|,就是加进去)

代码如下:

const int maxx=270000+10;
int dp[maxx][20],arr[20],up[20][20];




int check(int x)
{
    int cnt=0;
    while(x)
    {
        if(x%2) cnt++;
        x>>=1;
    }
    return cnt;
}




int main()
{
    ios::sync_with_stdio(false);
    int n,m,d;
    cin>>n>>m>>d;
    rep(i,0,n-1)
    {
        cin>>arr[i];
        dp[1<<i][i]=arr[i];
    }
    int u,v,w;
    rep(i,0,d-1)
    {
        cin>>u>>v>>w;
        u--,v--;
        up[u][v]=w;
    }
    int res=-1;
    rep(i,1,(1<<n))
    {
        rep(j,0,n-1)
        {
            if(i&(1<<j))
            {
                rep(k,0,n-1)
                {
                    if(i&(1<<k)) continue;
                    dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+arr[k]+up[j][k]);
                }
            }
            if(check(i)==m)
            res=max(res,dp[i][j]);
        }
    }
    cout<<res<<endl;
}

阅读全文
0 0
原创粉丝点击