• 10-18考试记


    10-18考试记

    300分。开心。

    1、咒语

    【题目描述】
    亮亮梦到自己来到了魔法城堡,但一扇巨大的石门阻拦了他通向城堡内的路。
    正当他沮丧之际,突然发现门上有一处机关,机关上有一张很长的纸条。
    亮亮拿起纸条的一端,只见上面写着打开机关的方法:“打开机关需要念动
    符咒,咒语是一串长为 L 的由 0 和 1 组成的字符串。在这张长纸条上列了 n 个
    长为 L 的字符串,正确的咒语即是在纷繁的 2^L 种字符串中,与这些纸条上的
    字符串相异度之和最小,并且在满足这一条件下,0 的个数最多的字符串。两个
    字符串的相异度定义为对应位置不相等的字符对的个数。如‘011’和‘001’的
    相异度为 1,因为它们有且只有第二个位置上的字符不相等。”
    亮亮拉起纸条,只觉得纸条似乎永远也拉不完。这上面有着数以万计的字符
    串,而每一个字符串的长度也或百或千,以人力看来是无法得到正确的咒语。你
    能帮帮他,让他得以进入魔法城堡,一窥其中的奥秘吗?
    【输入格式】
    第一行为一个数字 N 。
    接下来的 N 行,每行为一个长为 L 的 01 字符串。数据保证 N 个字符串等长。
    【输出格式】
    只有一行,是一个长为 L 的字符串 S,即为正确的咒语。

    记录每一位有多少个1就行了。

    code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int wx=3017;
    
    inline int read(){
    	int sum=0,f=1; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    	return sum*f;
    }
    
    char c[wx][wx];
    int l[wx];
    int n;
    
    
    //l[i]表示i这一位有多少个1
    //如果这一位的1个数多于0,那么这一位答案为1
    //否则为0 
    //暴力打不出来。。。
    
    //SB吧打啥暴力 
    
    int main(){
    	freopen("curse.in","r",stdin);
    	freopen("curse.out","w",stdout);
    	
    	n=read();
    	for(int i=1;i<=n;i++)scanf("%s",c[i]+1);
    	int len=strlen(c[1]+1);
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=len;j++){
    			if(c[i][j]=='1')l[j]++;
    		}
    	} 
    	for(int i=1;i<=len;i++){
    		if(l[i]<=(n-l[i]))printf("0");
    		else printf("1");
    	}
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    2、神光

    【题目描述】
    亮亮成功地念出了咒语,石门缓缓地自动移开,一道道绚丽的神光从城堡内
    激射而出。亮亮好奇而又兴奋地走入了城堡中,迎面有一座极长的魔法阵。
    魔法阵可以看作一条直线,它被均匀地分成了 1 000 000 000 个位置,一个位
    置可以看成是一个格子。有些位置上筑有法坛,一共 N 座。亮亮只有破了眼前
    的魔法阵,才能继续前进,而欲破法阵,必须毁掉所有的法坛。
    亮亮身前有两根法杖:一根颜色血红,能发红色神光,光芒可以笼罩连续 L
    个位置,并摧毁这 L 个位置上所有的法坛,最多使用 R 次;另一根颜色碧绿,
    能发绿色神光,光芒可以笼罩连续 2L 个位置,并摧毁这 2L 个位置上所有的法
    坛,最多使用 G 次。
    法杖的神奇之处在于,L 的值必须由亮亮事先设定好,并且一经设定,便无
    法更改。亮亮需要在规定的次数下摧毁所有法坛,并且使得 L 最小。
    【输入格式】
    第一行三个整数 N, R, G。
    第 i (2<=i<=n+1) 行一个整数Ai,表示第 i 座法坛的位置。
    【输出格式】
    只有一个整数,表示 L 的最小值。

    发现数据里的线索 缩小一下DP就可以了。

    这个DP的思路还是不错的。

    code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int wx=3017;
    
    inline int read(){
    	int sum=0,f=1; char ch=getchar();
    	while(ch<='0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    	return sum*f;
    }
    
    int pos[wx],f[wx][wx];
    int rr[wx],gg[wx];
    int n,R,G,ans;
    
    //二分?
    //这数据范围真TM神了
    //不太对,R+G>N直接有解1完事。
    //OK DP+二分吧 
    
    bool ok(int L){
    	memset(f,0,sizeof f);
    	memset(rr,0,sizeof rr);
    	memset(gg,0,sizeof gg);
    	rr[n+1]=n; gg[n+1]=n;
    	for(int i=1;i<=n;i++){
    		rr[i]=upper_bound(pos+1,pos+1+n,pos[i]+L-1)-pos-1;
    		gg[i]=upper_bound(pos+1,pos+1+n,pos[i]+L*2-1)-pos-1;
    	}
    	for(int i=0;i<=R;i++){
    		for(int j=0;j<=G;j++){
    			if(i)f[i][j]=max(f[i][j],rr[f[i-1][j]+1]);
    			if(j)f[i][j]=max(f[i][j],gg[f[i][j-1]+1]);
    		}
    	}
    	if(f[R][G]==n)return true;
    	return false;
    }
    
    int main(){
    	freopen("light.in","r",stdin);
    	freopen("light.out","w",stdout);
    	
    	n=read();R=read();G=read();
    	for(int i=1;i<=n;i++)pos[i]=read();
    	if(R+G>n){
    		puts("1");
    		return 0;
    	}
    	sort(pos+1,pos+1+n);
    	int l=1; int r=pos[n]-pos[1]+1;
    	while(l<=r){
    		int mid=l+r>>1;
    		if(ok(mid))ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	printf("%d
    ",ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    /*
    2zz3
    2zz3
    3zz3
    1zz2
    2zz2
    3zz3
    1zz1
    2zz2
    3zz3
    1zz1
    2zz2
    3zz3
    1zz2
    2zz2
    3zz3
    */
    

    3、迷宫

    【题目描述】
    破了魔法阵后,亮亮进入了一座迷宫。这座迷宫叫做“梦境迷宫”,亮亮只
    有走出这座迷宫,才能从睡梦中醒来。
    梦境迷宫可以用无向图来表示。它共有 n 个点和 m 条双向道路,每条道路
    都有边权,表示通过这条道路所需的时间,且每条道路可以多次经过。亮亮位于
    一号点,而出口则是 n 号点。原本,亮亮该找到一条最短路,快速冲出迷宫,然
    而,梦境迷宫的特殊之处在于,如果沿着最短路到达出口,亮亮就会永远陷入梦
    境。因此,亮亮必须寻找一条次短路。次短路的长度须严格大于最短路(可以有
    多条)的长度,同时又不大于所有除最短路外的道路的长度。
    你的任务,就是编写一个程序,帮助亮亮找到通向出口的次短路。
    【输入格式】
    第一行有两个整数 n、m,表示迷宫内共有 n 个点,m 条边。
    接下来 m 行,每行三个整数 x、y、z,表示结点 x 和 y 之间连有一条边权为
    z 的无向边。

    两边Dij,再枚举边就可以了。

    code:

    #include <iostream>
    #include <cstdio>
    #include <queue>
    
    #define int long long
    
    using namespace std;
    
    const int wx=500177;
    
    inline int read(){
    	int sum=0,f=1; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    	return sum*f;
    }
    
    int n,m,ans=0x7fffffff;
    int num;
    int head[wx],diss[wx],dist[wx],vis[wx];
    
    struct e{
    	int nxt,to,dis;
    }edge[wx*2];
    
    void add(int from,int to,int dis){
    	edge[++num].nxt=head[from];
    	edge[num].to=to;
    	edge[num].dis=dis;
    	head[from]=num;
    }
    
    struct node{
    	int u,d;
    	friend bool operator < (const node & a,const node & b){
    		return a.d>b.d;
    	}
    };
    
    priority_queue<node > q;
    
    void Dijs(){
    	for(int i=1;i<=n;i++)diss[i]=0x7fffffff,vis[i]=0;
    	q.push((node){1,0});diss[1]=0;
    	while(q.size()){
    		int u=q.top().u; q.pop();
    		if(vis[u])continue; vis[u]=1;
    		for(int i=head[u];i;i=edge[i].nxt){
    			int v=edge[i].to;
    			if(diss[v]>diss[u]+edge[i].dis){
    				diss[v]=diss[u]+edge[i].dis;
    				q.push((node){v,diss[v]});
    			}
    		}
    	}
    }
    
    void Dijt(){
    	for(int i=1;i<=n;i++)dist[i]=0x7fffffff,vis[i]=0;
    	q.push((node){n,0});dist[n]=0;
    	while(q.size()){
    		int u=q.top().u; q.pop();
    		if(vis[u])continue; vis[u]=1;
    		for(int i=head[u];i;i=edge[i].nxt){
    			int v=edge[i].to;
    			if(dist[v]>dist[u]+edge[i].dis){
    				dist[v]=dist[u]+edge[i].dis;
    				q.push((node){v,dist[v]});
    			}
    		}
    	}
    }
    
    void work(){
    	int beg=diss[n];
    	for(int u=1;u<=n;u++){
    		for(int i=head[u];i;i=edge[i].nxt){
    			int v=edge[i].to;
    			int tmp=diss[u]+dist[v]+edge[i].dis;
    			if(tmp>beg&&tmp<ans)ans=tmp;
    		}
    	}
    }
    
    //。。。T3是傻逼题 
    
    signed main(){
    	freopen("maze.in","r",stdin);
    	freopen("maze.out","w",stdout);
    	
    	n=read(); m=read();
    	for(int i=1;i<=m;i++){
    		int x,y,z;
    		x=read(); y=read(); z=read();
    		add(x,y,z); add(y,x,z);
    	}
    	Dijs();
    	Dijt();
    	work();
    	printf("%lld
    ",ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    继续加油。

  • 相关阅读:
    实验一 GIT 代码版本管理
    DS博客作业05--查找
    DS博客作业04--图
    DS博客作业03--树
    DS博客作业02--栈和队列
    DS博客作业01-线性表
    C博客作业05--2019-指针
    C语言博客作业04--数组
    C语言博客作业03--函数
    python exp4 jieba+wordcloud
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9809301.html
Copyright © 2020-2023  润新知