zoukankan      html  css  js  c++  java
  • 【考试题

    没有测试数据,但是和正解对拍了 400 多组数据都过了.   

    手画一下发现每个数如果变化的话只有 3 种情况:$-1,0,1$.   

    感性理解的话一个数变小的话对前面更优,对后面更劣.       

    但是我们发现不可能存在一个数使得该数变小后会导致后面的数也变小.  

    这是因为如果该数变小的话说明该数和前缀最小值已经构成 $max$,而如果后面的数大于当前数的话显然只需要分析前缀最小值和后面的数就行了.     

    变小的情况这么分析,变大的情况同理.    

    令 $f[i][j]$ 表示做到 $i$ 位,前缀最小值是原前缀最小值+$j$,时间复杂度为 $O(3^2 n)$.     

    这道题的数据并不好造,因为如果值域过于分散的话答案就是 1.     

    所以我们可以生成一个长度为 $10^5$ 的数组,然后数组中的每个元素的值域为 $[-100,100]$.   

    这么造出来的数据效果不错,答案一般能超过 $10^3.$   

    代码:  

    #include <cstdio> 
    #include <cstring>
    #include <algorithm>   
    #define N 1000009  
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;    
    const int con[]={-1,0,1};  
    const int pri[]={1,0,1};  
    const int inf=1000000003;    
    int dp[N][3],mi[N],val[N],n; 
    int get(int x) { 
    	if(x==-1) return 0;  
    	if(x==0)  return 1; 
    	if(x==1)  return 2;  
    	return 23; 
    }
    int main() { 
    	// setIO("input");   
    	scanf("%d",&n);    
    	mi[0]=inf;     
    	int fax=0; 
    	for(int i=1;i<=n;++i) { 
    		scanf("%d",&val[i]);  
    		mi[i]=min(mi[i-1],val[i]);    
    		fax=max(fax,val[i]-mi[i]);  
    	}         
    	// 存好前缀最小值.   	    
    	memset(dp,0x3f,sizeof(dp));  
    	dp[0][1]=0;  
    	for(int i=1;i<=n;++i) {    
    		for(int x=0;x<3;++x)   
    			for(int y=0;y<3;++y) {    
    				if(val[i]+con[x]-(mi[i-1]+con[y])>=fax) {   
    					continue;  
    				}
    				int cur=min(mi[i-1]+con[y],val[i]+con[x]);              
    				int p=get(cur-mi[i]);        
    				dp[i][p]=min(dp[i][p],dp[i-1][y]+pri[x]);  
    			}     
    	}    	    
    	int ans=inf;  
    	for(int i=0;i<3;++i) { 
    		ans=min(ans,dp[n][i]);  
    	}  
    	printf("%d
    ",ans);   
    	return 0;
    }
    

      

    对拍:  

    #include <bits/stdc++.h> 
    #define N 1000009  
    using namespace std;
    int a[N];  
    void gen() { 
        FILE *fp=fopen("input.in","w");   
    	int n=100000;  
    	a[1]=1,a[n]=9;  
    	for(int i=2;i<n;++i) {    
    		int p=rand()%100; 
    		if(p&1) a[i]=-p;  
    		else a[i]=p;  
    	}  
    	fprintf(fp,"%d
    ",n); 
    	for(int i=1;i<=n;++i) { 
    		fprintf(fp,"%d ",a[i]);  
    	}  
    	fprintf(fp,"
    "); 
        fclose(fp);  
    }          
    void test() { 
        FILE *fp=fopen("input.in","w");  
        fprintf(fp,"%d %d
    ",rand(),rand());    
        fclose(fp);  
    }
    int main() { 
        system("g++ a.cpp -o a.exe -g -O2");  
        system("g++ b.cpp -o b.exe -g -O2");  
        srand(time(NULL));       
        rand();         
        int cnt=0;
        while(1) { 
            gen();  
            system("a.exe < input.in > input.out");  
            system("b.exe < input.in > de.out");   
            if(system("fc input.out de.out > FC.out"))  { 
                printf("WA
    "); 
                exit(0); 
            }   
            else {  
                printf("AC %d
    ",++cnt);  
            }
        }
        return 0;     
    }
    

      

  • 相关阅读:
    火狐插件火狐黑客插件将Firefox变成黑客工具的七个插件
    memcache安装环境:WINDOWS 7
    PHP正则表达式
    968. 监控二叉树 力扣(困难) dfs 官方说DP
    375. 猜数字大小 II 力扣(中等) 区间动态规划、记忆化搜索
    629. K个逆序对数组 力扣(困难) 区间动态规划
    剑指 Offer 51. 数组中的逆序对 力扣(困难) 巧用归并排序算法
    488. 祖玛游戏 力扣(困难) dfs
    16. 最接近的三数之和 力扣(中等) 双指针
    319. 灯泡开关 力扣(中等) 数论
  • 原文地址:https://www.cnblogs.com/guangheli/p/13433862.html
Copyright © 2011-2022 走看看