zoukankan      html  css  js  c++  java
  • 【bzoj3671】[Noi2014]随机数生成器 贪心

    题目描述

    输入

    第1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子。第2行包含三个整数 N,M,Q ,表示小H希望生成一个1到 N×M 的排列来填入她 N 行 M 列的棋盘,并且小H在初始的 N×M 次交换操作后,又进行了 Q 次额外的交换操作。接下来 Q 行,第 i 行包含两个整数 u_i,v_i,表示第 i 次额外交换操作将交换 T_(u_i )和 T_(v_i ) 的值。

    输出

    输出一行,包含 N+M-1 个由空格隔开的正整数,表示可以得到的字典序最小的路径序列。

    样例输入

    1 3 5 1 71
    3 4 3
    1 7
    9 9
    4 9

    样例输出

    1 2 6 8 9 12


    题目大意

    给定你一个用乱七八糟的方法生成的n*m的矩阵,矩阵中的元素是1~n*m的全排列,问从左上走到右下的路径中,把经过的元素从小到大排序后得到的字典序最小的路径是什么

    题解

    贪心

    其实我真不知道出题人是怎么想的,题目描述搞得和数论似的,结果目的就是给出这个序列 = =

    显然要考虑从小到大的n*m个数,如果能选就选,选了就更新其它不能选的位置。

    如果一个点被选择,那么它的严格左下方和严格右上方的点都不能被选择,开一个标记数组记录它。

    如果扫到一个点,它已经被标记过,那么它的左下(或右上)的点一定都被标记过。适当终止循环,时间复杂度是均摊$O(nm)$的。

    但是本题卡内存差评,所以不能开数组记录每次的x,标记数组必须开成bool的等等。

    另外本题需要使用桶排序,否则会TLE。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int val[25000010] , pos[25000010];
    bool tag[5010][5010];
    int main()
    {
    	int a , b , c , d , n , m , k , q , i , jx , jy , px , py , cnt = 0;
    	long long x;
    	scanf("%lld%d%d%d%d%d%d%d" , &x , &a , &b , &c , &d , &n , &m , &q) , k = n * m;
    	for(i = 1 ; i <= k ; i ++ ) val[i] = i , x = (a * x * x + b * x + c) % d , pos[i] = (int)x;
    	for(i = 1 ; i <= k ; i ++ ) swap(val[i] , val[pos[i] % i + 1]);
    	while(q -- ) scanf("%d%d" , &px , &py) , swap(val[px] , val[py]);
    	for(i = 1 ; i <= k ; i ++ ) pos[val[i]] = i;
    	for(i = 1 ; i <= k ; i ++ )
    	{
    		px = (pos[i] - 1) / m + 1 , py = (pos[i] - 1) % m + 1;
    		if(!tag[px][py])
    		{
    			printf("%d%c" , i , ++cnt == n + m - 1 ? '
    ' : ' ');
    			if(py > 1)
    			{
    				for(jx = px + 1 ; jx <= n ; jx ++ )
    				{
    					if(tag[jx][py - 1]) break;
    					for(jy = py - 1 ; jy >= 1 ; jy -- )
    					{
    						if(tag[jx][jy]) break;
    						tag[jx][jy] = 1;
    					}
    				}
    			}
    			if(py < m)
    			{
    				for(jx = px - 1 ; jx >= 1 ; jx -- )
    				{
    					if(tag[jx][py + 1]) break;
    					for(jy = py + 1 ; jy <= m ; jy ++ )
    					{
    						if(tag[jx][jy]) break;
    						tag[jx][jy] = 1;
    					}
    				}
    			}
    		}
    	}
    	return 0;
    }
    

     

  • 相关阅读:
    DS博客作业02--线性表
    DS博客作业01--日期抽象数据类型设计与实现
    C语言博客作业06--结构体&文件
    C语言博客作业05--指针
    C语言博客作业04--数组
    DS博客作业8——课程总结
    DS博客作业07——查找
    DS博客作业06--图
    DS博客作业——树
    DS博客作业03--栈和队列
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7128334.html
Copyright © 2011-2022 走看看