zoukankan      html  css  js  c++  java
  • 环形的处理P1880 [NOI1995]石子合并

    Description

    在一个圆形操场的四周摆放 N 堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
    试设计出一个算法,计算出将 N 堆石子合并成 1堆的最小得分和最大得分。

    数据的第 1 行是正整数 N,表示有N堆石子。
    第 2 行有 N个整数,第 i 个整数 (a_i)表示第 i 堆石子的个数。
    输出共 2 行,第 1 行为最小得分,第 2行为最大得分。

    Input

    4
    4 5 9 4

    Output

    43
    54

    Analysis

    决策容易分析,最优子结构有两部分
    断环为链:将长度为n的链复制一份接在后面,环的情况就是长度为2n的链中任意连续的长度为n的链。

    Code

    我的写法

    #include<bits/stdc++.h>
    using namespace std;
    int s[101],a[100],xp[100][100],dp[100][100];
    int main(){
        int n,i,j,maxi=0,mini=200000;scanf("%d",&n);
        for(i=0;i<n;++i){
            scanf("%d",&a[i]);
            s[i+1]=s[i]+a[i];s[i+1+n]=s[i+1];
        }
        for(i=0;i<n;++i)s[i+1+n]+=s[n];
        for(int z=1;z<n;++z)for(i=0;i<n;++i){        
            j=i+z;xp[i][j%n]=200000;
            for(int k=i;k<j;++k){
                xp[i][j%n]=min(xp[i][j%n],xp[i][k%n]+xp[(k+1)%n][j%n]+s[j+1]-s[i]);
                dp[i][j%n]=max(dp[i][j%n],dp[i][k%n]+dp[(k+1)%n][j%n]+s[j+1]-s[i]);
                if(z==n-1)mini=min(mini,xp[i][j%n]);
                if(z==n-1)maxi=max(maxi,dp[i][j%n]);
            }
        }
        printf("%d
    %d",mini,maxi);
        return 0;
    }
    

    另一种写法

    #include<bits/stdc++.h>
    using namespace std;
    int n,l,anss,ansb,a[110],sum[210],dp[210][210],dpbig[210][210];
    int main(){
    	memset(dp,0x3f,sizeof(dp)); anss=dp[0][0];
    	cin>>n;
    	for (int i=1;i<=n;i++) cin>>a[i]; a[0]=a[n];
    	for (int i=1;i<=2*n;i++){
    		sum[i]=sum[i-1]+a[i%n];
    		dp[i][i]=0;
    	}
    	for (int len=2;len<=n;len++){
    		for (int r=len;r<=2*n;r++){
    			l=r-len+1;
    			for (int j=l;j<r;j++){
    				dp[l][r]=min(dp[l][j]+dp[j+1][r]+sum[r]-sum[l-1],dp[l][r]);
    				dpbig[l][r]=max(dpbig[l][j]+dpbig[j+1][r]+sum[r]-sum[l-1],dpbig[l][r]);
    			}
    		}
    	}
    	for (int i=1;i<=n;i++){
    		anss=min(dp[i][i+n-1],anss);
    		ansb=max(dpbig[i][i+n-1],ansb);
    	}
    	cout<<anss<<endl;
    	cout<<ansb;
    	return 0;
    }
    
  • 相关阅读:
    记录上锁(字节范围锁,特例:锁住文件的某一部分或者整个文件)
    读写锁的实现原理(pthread_rwlock_t)
    Linux 互斥锁的实现原理(pthread_mutex_t)
    System V消息队列
    Web安全之SQL注入攻击技巧与防范
    如何正确地写出单例模式
    java的concurrent用法详解
    java并发编程-Executor框架
    java.util.concurrent包分类结构图
    Java多线程干货系列(1):Java多线程基础
  • 原文地址:https://www.cnblogs.com/chanceYu/p/12163451.html
Copyright © 2011-2022 走看看