zoukankan      html  css  js  c++  java
  • 11.4 校内模拟赛解题报告

    T1

    尽量先找面额大的,然后找面额小的。

    int main()
    {
    	n = read();
    	for(int i = 1; i <= n; i++)
    	{
    		int x = read();
    		if(x == 5) a++;
    		if(x == 10)
    		{
    			if(a != 0) a--, b++;
    			else {puts("NO"); return 0;}
    		}
    		if(x == 20)
    		{
    			if(b != 0 && a != 0) a--, b--;
    			else if(a >= 3) a -= 3;
    			else {puts("NO"); return 0;}
    		}
    	}
    	puts("YES");
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    T2

    考场上写了一个用栈正序维护的错误做法,维护栈中每个数字的个数,和已知出口数字的个数,怎么看怎么对。但是并不对。
    正解:用栈倒叙维护,每次栈顶的绝对值与当前数的绝对值不相同,就将当前数变成负数进栈,如果相同且栈顶为负,则出栈。

    /*
    Date:
    Source:
    Knowledge: 用栈维护,倒着来 
    */
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #define orz cout << "AK IOI" << "
    "
    
    using namespace std;
    const int maxn = 1e6 + 10;
    
    int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    void print(int X)
    {
    	if(X < 0) X = ~(X - 1), putchar('-');
    	if(X > 9) print(X / 10);
    	putchar(X % 10 ^ '0');
    }
    int Max(int a, int b){
    	return a > b ? a : b;
    }
    int Min(int a, int b){
    	return a < b ? a : b;
    }
    int n, m, a[maxn], vis[maxn];
    int top, st[maxn];
    int main()
    {
    	//freopen("program1.in", "r", stdin);
    	//freopen("program.out", "w", stdout);
    	n = read();
    	for(int i = 1; i <= n; i++) a[i] = read(), vis[a[i]]++;
    	for(int i = 1; i <= n; i++)
    		if(vis[a[i]] % 2 == 1) {puts("NO"); return 0;}
    	m = read();
    	for(int i = 1; i <= m; i++)
    	{
    		int x = read();
    		if(a[x] > 0) a[x] = -a[x];    	
    	}
    	for(int i = n; i >= 1; i--)
    	{
    		if(abs(st[top]) != abs(a[i])) 
    		{
    			if(a[i] > 0) st[++top] = -a[i], a[i] = -a[i];
    			else st[++top] = a[i];
    		}
    		else
    		{
    			if(a[i] > 0) top--;
    			else st[++top] = a[i];
    		}
    	} 
    	for(int i = 1; i <= n; i++) 
    	{
    		if(a[i] < 0) printf("%d ", a[i]);
    		else printf("+%d ", a[i]);
    	}
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    T3

    将钥匙看做左括号,门看做右括号,模拟括号匹配,将问题转化为 从 (a) 走到 (b) 能否完成括号匹配。

    宽搜 + DP。

    (f[i][j][k]) 表示点 (i) 到点 (j) 是否有状态 (k)
    (k = 0) 表示 (i)(j) 的路径上能够括号匹配。
    (k:1 — 10) 表示点 (i)(j) 的路径上,栈顶为右括号 (k)
    (k:11 — 20) 表示点 (i)(j) 的路径上,栈顶为左括号 (k),即缺右括号 (k)

    每次更新一个 (i j k),就相当于在 (i j) 之间连一条状态为 (k) 的边,让这条边进队。
    (w < 0) 的时候边是不进队的,因为有了左括号后可以接右括号,而右括号后不能接左括号。

    从队列里取出从 (u)(v) 的状态为 (w) 的边。
    如果 (w = 0),那么枚举状态 (k (0, 11—20)) 进行更新。
    如果 (w != 0),那么只能去找右括号。
    具体看代码。
    为什么 (w=0) 是双向更新,(w!=0) 是单项更新?
    因为只能是栈中有左括号的情况下,只有右括号才能入栈。
    对于每一次询问,判断 (f[u][v][0]) 即可。

    /*
    Date:
    Source:
    Knowledge:f[i][j][k] 表示点i到点j 是否有状态k
    */
    #include <iostream>
    #include <cstdio>
    #include <queue>
    #define orz cout << "AK IOI" << "
    "
    
    using namespace std;
    const int maxn = 110;
    
    int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    void print(int X)
    {
    	if(X < 0) X = ~(X - 1), putchar('-');
    	if(X > 9) print(X / 10);
    	putchar(X % 10 ^ '0');
    }
    int Max(int a, int b){
    	return a > b ? a : b;
    }
    int Min(int a, int b){
    	return a < b ? a : b;
    }
    int n, m, Q;
    bool f[maxn][maxn][25];
    struct node{
    	int u, v, w;
    };
    queue <node> q;
    int main()
    {
    	n = read(), m = read();
    	for(int i = 1; i <= n; i++) f[i][i][0] = 1; 
    	for(int i = 1; i <= m; i++)
    	{
    		int u = read(), v = read(), w = read();
    		if(w == 0)
    		{
    			f[u][v][w] = f[v][u][w] = 1;
                q.push((node){u, v, w}); 
                q.push((node){v, u, w}); 
    		}
    		else if(w > 0)//钥匙  
    		{
    			w += 10;
                f[u][v][w] = f[v][u][w] = 1;
                q.push((node){u, v, w}); 
                q.push((node){v, u, w}); 
    		}
    		else w = -w, f[u][v][w] = f[v][u][w] = 1; //门 
    	}
    	while(!q.empty())
    	{
    		node t = q.front();
    		q.pop();
    		int u = t.u, v = t.v, w = t.w;
    		if(w == 0)//大前提是已经有一条权值为 0 的边连通 u,v, 此时是一条有向边, 类比最短路。 
    		{
    			for(int i = 1; i <= n; i++)
    			{
    				if(f[i][u][0] && !f[i][v][0]) 
                	{
                	    f[i][v][0] = 1;
               	     	q.push((node){i, v, 0});
                	}
                	if(f[v][i][0] && !f[u][i][0])
                	{
                	    f[u][i][0] = 1;
                	    q.push((node){u, i, 0});
                	}
    				for(int k = 11; k <= 20; k++)
    				{
    					if(f[i][u][k] == 1 && !f[i][v][k]) f[i][v][k] = 1, q.push((node){i, v, k});
    					//if(f[i][v][k] == 1 && !f[i][u][k]) f[i][u][k] = 1, q.push((node){i, u, k});
    				}
    			}
    		}
    		else 
    		{
    			for(int i = 1; i <= n; i++)
                {
                    if(f[v][i][w - 10] && !f[u][i][0]) // w 属于(1 - 10) 并没有入队 
                    {
                        f[u][i][0] = 1;
                        q.push((node){u, i, 0});
                    }
                }
    		}
    	}
    	Q = read();
    	for(int i = 1; i <= Q; i++)
    	{
    		int a = read(), b = read();
    		if(f[a][b][0] == 1) puts("YES");
    		else puts("NO");
    	}
    	//fclose(stdin);
    	//fclose(stdout);
    	return 0;
    }
    
    
  • 相关阅读:
    Linux基础之计算机硬件
    python中 __cmp__
    python中 __str__和__repr__
    python的构造函数传入任意数量的参数
    python中的偏函数
    javascript正则表达式
    js实现复选框的全选、全部选和反选
    js中的函数对象
    js中的作用域
    js中的arguments
  • 原文地址:https://www.cnblogs.com/yangchengcheng/p/15509306.html
Copyright © 2011-2022 走看看