ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

高考集训3

2022-06-08 19:34:45  阅读:175  来源: 互联网

标签:ch int 高考 zhen WR include 集训 define


110分

【比赛】2022高考集训3 - 比赛 - 衡中OI (hszxoj.com)

1.单调队列优化DP

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<bitset>
#include<map>
#include<queue>
#include<bitset>
#include<deque>
#include<vector>
#define _f(i,a,b)  for(register int i=a;i<=b;++i)

#define f_(i,a,b)  for(register int i=a;i>=b;--i)

#define ll long long

#define chu printf


using namespace std;
inline int re()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
const int WR=1001000;ll INF=1e18;
struct firework
{
    int a,b,t;
}fire[400];
ll tmp[160000],f[160000];
int n,m,d;
int l,r;
int que[160000];
int main()
{
    freopen("fire.in","r",stdin);
    freopen("fire.out","w",stdout);
    n=re(),m=re(),d=re();
    _f(i,1,m)
    {
        fire[i].a=re(),fire[i].b=re(),fire[i].t=re();
    }
    for(int i=1;i<=m;i++)//f[i][j]:i烟花在j时刻绽放最大幸福值
    {
        memcpy(tmp,f,sizeof(f));
        int k=1;//当前扩展到的位置 
        ll dis=(ll)(fire[i].t-fire[i-1].t)*d;
        l=1,r=0;//初始为空.....吗? 
        for(int j=1;j<=n;j++)
        {
            while(k<=min((ll)n,j+dis))//最多拓展到的位置
            {
                while(l<=r&&tmp[que[r]]<=tmp[k])r--;//值递减,不然就没有必要要那个que[r]了,离的远还小 
                que[++r]=k;
                k++;
            }
            while(l<r&&j-que[l]>dis)l++;//必须剩下一个,但是是这么剩吗??
             f[j]=tmp[que[l]]+fire[i].b-abs(fire[i].a-j);
        }
     } 
     ll maxans=-INF;
     _f(i,1,n)maxans=max(maxans,f[i]);
     chu("%lld",maxans);
    return 0;
}
/*
DP单调队列优化
满足:
位置单调
多项式中的每一项只和j或者k有关 
f[i][j]=max(f[i-1][k]+summ)
abs(j-k)<=d*(time(i)-time(i-1))
直接枚举k肯定会超时
考虑单调性问题
f[i]固定
在j不断变大的过程中,我肯定是从f[i-1]选择一个位置转移
假设posm,posn
如果posm<posn,f[i-1][posm]<=f[i-1][posn]
 posm一定没用,我就可以扔了
 所以
 枚举n时:维护单调递减的队列 
     拓展新的可能位置(往右边动了多少)
     维护队头合法性(dis能到达)
     对头就是最优解 
*/

2.无脑DP

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<bitset>
#include<map>
#include<queue>
#include<bitset>
#include<deque>
#include<vector>
#define _f(i,a,b)  for(register int i=a;i<=b;++i)

#define f_(i,a,b)  for(register int i=a;i>=b;--i)

#define ll long long

#define chu printf

#define INF 0x7f7f7f7f
/*说真的,必须向秋英学习
1.样例对了什么都不是,你要把每一个细节抠死,保证代码
过程0问题
2.学会归纳,不是什么都必须记住,但是经常考的必须记住
3.思路灵活不怕麻烦,敢想就敢使劲写 
*/ 
using namespace std;
inline int re()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
const int SIZE=400;
int n,k;
int f[1200][13];
struct city
{
    int to[13][32],sz,rod[13];
} C[13];
inline void DP()
{
    for(int i=0;i<=k+1;i++)
    for(int j=0;j<=n;j++)f[i][j]=INF;
    f[1][1]=0;//初始化,从实际意义考虑 
    _f(i,2,k+1)
    {
        _f(j,1,n)
        {
            _f(kk,1,n)//这里的kk一定不能和上面的重复 
            {
                
                if(j==kk)continue;
            //    if(i==2&&(kk!=1))continue;//第二天只能从第一天转移
            
                int res=(i-1)%C[kk].rod[j];
            //    chu("(%d)modC[%d].rod[%d]:%d    :%d\n",i-1,kk,j,C[kk].rod[j],res);
                if(res==0)res=C[kk].rod[j];//如果res==0,应该是这样而不是==i-1,想清楚 
            //    chu("res:%d\n",res);
                int cost=C[kk].to[j][res];
                if(cost==0)continue;
            //        chu("i:%d\n",i);
                f[i][j]=min(f[i][j],f[i-1][kk]+cost);
            //    if(i==k+1)chu("f[%d][%d]:%d\n",i,j,f[i][j]);
            }
        }
    }
    int answer=f[k+1][n];
    if(answer==INF)chu("0\n");
    else chu("%lld\n",answer);
}
int main()
{
    freopen("perform.in","r",stdin);
    freopen("perform.out","w",stdout);
    while(scanf("%d%d",&n,&k)!=EOF)//n!=0,k!=0
    {
        if(n==0&&k==0)break;
        _f(i,1,n)
        {
            C[i].sz=0;
            _f(j,1,n)
            {
                if(j==i)continue;
                C[i].rod[j]=re();
                _f(k,1,C[i].rod[j])
                {
                    C[i].to[j][k]=re();
                }
            }
        }
        DP();
    }
    return 0;
}
/*
3 6
2 130 150
3 75 0 80
7 120 110 0 100 110 120 0
4 60 70 60 50
3 0 135 140
2 70 80
2 3
2 0 70
1 80
3 6
2 130 150
3 75 0 80
7 120 110 0 100 110 120 0
4 60 70 60 50
3 0 135 140
2 70 80
0 0

3 10
5 1 1 1 1 1
5 1 1 1 1 1
5 1 1 1 1 1
5 1 1 1 1 1
5 1 1 1 1 1
5 1 1 1 1 1
*/

3.图论的相关知识+思维

学会自己找性质和结论

const int SIZE=400;
const int WR=1001000;
int n,aim[WR];
int ipt[WR];
int lve,sze;
int que[WR],pos;
bool kill[WR],exist[WR];
int main()
{
    freopen("maf.in","r",stdin);freopen("maf.out","w",stdout);
    n=re();
    _f(i,1,n)aim[i]=re(),ipt[aim[i]]++;
    _f(i,1,n)
    {
        if(ipt[i]==0)
        {
            lve++;que[++sze]=i;
        }
    }
    pos=1;
    while(pos<=sze)
    {
        int frnt=que[pos];//取出那个(起初)一定是不死 
        pos++;
        if(kill[aim[frnt]])continue;//如果不死神的目标死了,走掉 
        kill[aim[frnt]]=true;
        int targ=aim[aim[frnt]];//不死神的目标的目标,目标一定死,目标的目标不一定 
        ipt[targ]--;//假如目标死了,那targ当前就成了不死神2 
        exist[targ]=true;//是被救的 
        if(!ipt[targ])que[++sze]=targ; 
    }
    _f(i,1,n)
    {
        if(ipt[i]&&!kill[i])
        {
            int ring=0;
            bool flag=false;
            for(int j=i;!kill[j];j=aim[j])
            {
                ring++;
                if(exist[j])flag=true;
                kill[j]=true;
            }
            if(!flag&&ring>1)lve++;//排除自环 
            sze+=ring/2;
        }
    }
    chu("%d %d",n-sze,n-lve);
    return 0;
}

4.结论+固定条件+简单唯一枚举

const int SIZE=400;
bool zhen[5][5];
bool fuben[5][5];int tot;
inline void cpy()
{
    _f(i,1,4)
    {
        _f(j,1,4)zhen[i][j]=fuben[i][j];
    }
}
char s[5][5];
inline void maketurn(int x,int y)
{
    tot++;
    zhen[x+1][y]=!zhen[x+1][y];
    zhen[x-1][y]=!zhen[x-1][y];
    zhen[x][y-1]=!zhen[x][y-1];
    zhen[x][y+1]=!zhen[x][y+1];
    zhen[x][y]=!zhen[x][y];
}
int minans=INF;
inline bool check(bool p)
{
    _f(i,1,4)
    {
        _f(j,1,4)
        if(zhen[i][j]!=p)return false;
    }
    return true;
}

int main()
{
    freopen("flip.in","r",stdin);    freopen("flip.out","w",stdout);
    _f(i,1,4)
    {
        scanf("%s",s[i]+1);
        int dieC=0;
        _f(j,1,4)
        {
            if(s[i][j]=='w')zhen[i][j]=1,fuben[i][j]=1;
            //chu("%d ",zhen[i][j]);
        }
    //    chu("\n");
    }
    //枚举操作数,如果翻转就是1,不反转就是0
    _f(i,0,15)
    {
        cpy();
        tot=0;
        //i是操作就要干 
        _f(j,1,4)
        {
            if(i&(1<<(j-1)))
            {
                maketurn(1,j);
            }
        }
        //第一行
        _f(j,1,4)
        {
            if(zhen[1][j]!=0)maketurn(2,j);//先都变成0
        } 
        _f(j,1,4)//第二行
        {
            if(zhen[2][j]!=0)maketurn(3,j);
         } 
        _f(j,1,4)//第三行
        {
            if(zhen[3][j]!=0)maketurn(4,j);    
        } 
        if(check(0))minans=min(minans,tot);
    } 
    _f(i,0,15)
    {
        cpy();
        tot=0;
        //i是操作就要干 
        _f(j,1,4)
        {
            if(i&(1<<(j-1)))
            {
                maketurn(1,j);
            }
        }
        //第一行
        _f(j,1,4)
        {
            if(zhen[1][j]!=1)maketurn(2,j);//先都变成0
        } 
        _f(j,1,4)//第二行
        {
            if(zhen[2][j]!=1)maketurn(3,j);
         } 
        _f(j,1,4)//第三行
        {
            if(zhen[3][j]!=1)maketurn(4,j);    
        } 
    //    chu("isok?\n");
    //    chu("check:%d\n",check(1));
    //    chu("minans:%d  tot:%d\n",minans,tot);
        if(check(1))minans=min(minans,tot);
    } 
    if(minans==INF)chu("Impossible");
    else chu("%d",minans);
    return 0;
}
/*
枚举的前提是知道性质:
1.当第一行确定翻转,后面的反转方案唯一
2.反转顺序无所谓
3每个点如果反转超过1次即无解
枚举第一行状态
然后
枚举1 2,3 4
x,y==1,必须让x+1,y反转 
*/

 

标签:ch,int,高考,zhen,WR,include,集训,define
来源: https://www.cnblogs.com/403caorong/p/16356850.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有