T1 能量项链


原题

在Mars星球上,每个Mars人都随身佩带着一串能量项链。在项链上有N颗能量珠。能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数。并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记。因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量。如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为mrn(Mars单位),新产生的珠子的头标记为m,尾标记为n。

需要时,Mars人就用吸盘夹住相邻的两颗珠子,通过聚合得到能量,直到项链上只剩下一颗珠子为止。显然,不同的聚合顺序得到的总能量是不同的,请你设计一个聚合顺序,使一串项链释放出的总能量最大。

例如:设N=4,4颗珠子的头标记与尾标记依次为(2,3) (3,5) (5,10) (10,2)。我们用记号⊕表示两颗珠子的聚合操作,(j⊕k)表示第j,k两颗珠子聚合后所释放的能量。则第4、1两颗珠子聚合后释放的能量为:

(4⊕1)=1023=60。

这一串项链可以得到最优值的一个聚合顺序所释放的总能量为

((4⊕1)⊕2)⊕3)=1023+1035+10510=710。

输入输出格式

思路

  1. 将环解开,以2*n-1的长度平铺在桌上
  2. 设i,j为珠子的编号,f[i][j]表示合并i~j所有的珠子的最大能量,k表示断开的位置(即f[i][j]=f[i][k]+f[k][j])
  3. 接下来枚举每一种可能的i~j的长度p和k,并更新最大值

代码

#include <cstdio>
#include <iostream>
#include <cstring>
#define RG register
using namespace std;
const int maxn=300+5;
inline int read()
{int x=0,w=1;char ch=0;ch=getchar();while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();if(ch=='-') w=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*w;
}
int n;
long long head[maxn],tail[maxn],f[maxn][maxn];
int main(){n=read();for(RG int i=1;i<=n;i++) head[i]=read();for(RG int i=1;i<n;i++) tail[i]=head[i+1];tail[n]=head[1];int m=n*2-1;for(RG int i=n+1;i<=m;i++){head[i]=head[i-n];tail[i]=tail[i-n];}memset(f,0,sizeof(f));for(RG int p=1;p<=n-1;p++)   //枚举长度 for(RG int i=1;i<=m-1;i++){int j=i+p;             // i为头 j为尾 if(j>m) break;for(RG int k=i;k<=j-1;k++){    //枚举每一种断开位置 f[i][j]=max(f[i][k]+f[k+1][j]+head[i]*tail[k]*tail[j],f[i][j]);}}long long ans=0;for(RG int i=1;i<=n;i++) ans=max(ans,f[i][i+n-1]);  //从所有的断开位置中选出最大值 printf("%lld\n",ans);return 0;
}

T2 金明的预算方案


原题

金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:


思路

有条件的背包模型,可以枚举主件,有不取,取附件A,附件B,两个附件四种情况。
if j>=a[i,0] then f[j]:=max(f[j],f[j-a[i,0]]+a[i,0]*b[i,0]);//取主件
if j>=a[i,0]+a[i,1] then f[j]:=max(f[j],f[j-a[i,0]-a[i,1]]+a[i,0]*b[i,0]+a[i,1]*b[i,1]);//取第一个附件
if j>=a[i,0]+a[i,2] then f[j]:=max(f[j],f[j-a[i,0]-a[i,2]]+a[i,0]*b[i,0]+a[i,2]*b[i,2]);//取第二个附件
if j>=a[i,0]+a[i,1]+a[i,2] then f[j]:=max(f[j],f[j-a[i,0]-a[i,2]-a[i,1]]+a[i,0]*b[i,0]+a[i,2]*b[i,2]+a[i,1]*b[i,1]);//取三个附件


代码

#include<iostream>
using namespace std;
int main()
{int a,b,mx=0;int i,j;int m,n,v[61]={0},p[61]={0},q;int v1[61]={0},v2[61]={0},p1[61]={0},p2[61]={0};int f[50001]={0};cin>>m>>n;m/=10;for(i=1;i<=n;i++){cin>>a>>b>>q;a/=10;if(q!=0){if(v1[q]==0){v1[q]=a;p1[q]=b;}else {v2[q]=a;p2[q]=b;}}else {v[i]=a;p[i]=b;}}for(int i=1;i<=n;i++)for(int j=m;j>=v[i];j--){f[j]=max(f[j],f[j-v[i]]+v[i]*p[i]);if(j-v1[i]-v[i]>=0)f[j]=max(f[j],f[j-v1[i]-v[i]]+v1[i]*p1[i]+v[i]*p[i]);if(j-v2[i]-v[i]>=0)f[j]=max(f[j],f[j-v2[i]-v[i]]+v2[i]*p2[i]+v[i]*p[i]);if(j-v1[i]-v2[i]-v[i]>=0)f[j]=max(f[j],f[j-v1[i]-v2[i]-v[i]]+v1[i]*p1[i]+v2[i]*p2[i]+v[i]*p[i]);mx=max(f[j],mx);}cout<<mx*10;//system("pause");return 0;
}

作业调度方案


原题

我们现在要利用m台机器加工n个工件,每个工件都有m道工序,每道工序都在不同的指定的机器上完成。每个工件的每道工序都有指定的加工时间。
每个工件的每个工序称为一个操作,我们用记号j-k表示一个操作,其中j为1到n中的某个数字,为工件号;k为1到m中的某个数字,为工序号,例如2-4表示第2个工件第4道工序的这个操作。在本题中,我们还给定对于各操作的一个安排顺序。
例如,当n=3,m=2时,“1-1,1-2,2-1,3-1,3-2,2-2”就是一个给定的安排顺序,即先安排第1个工件的第1个工序,再安排第1个工件的第2个工序,然后再安排第2个工件的第1个工序,等等。

  • 一方面,每个操作的安排都要满足以下的两个约束条件。

    1. 对同一个工件,每道工序必须在它前面的工序完成后才能开始;
    2. 同一时刻每一台机器至多只能加工一个工件。
  • 另一方面,在安排后面的操作时,不能改动前面已安排的操作的工作状态。

由于同一工件都是按工序的顺序安排的,因此,只按原顺序给出工件号,仍可得到同样的安排顺序,于是,在输入数据中,我们将这个安排顺序简写为“1 1 2 3 3 2”。
还要注意,“安排顺序”只要求按照给定的顺序安排每个操作。不一定是各机器上的实际操作顺序。在具体实施时,有可能排在后面的某个操作比前面的某个操作先完成。
例如,取n=3,m=2,已知数据如下:

则对于安排顺序“1 1 2 3 3 2”,下图中的两个实施方案都是正确的。但所需要的总时间分别是10与12。
当一个操作插入到某台机器的某个空档时(机器上最后的尚未安排操作的部分也可以看作一个空档),可以靠前插入,也可以靠后或居中插入。为了使问题简单一些,我们约定:

  • 在保证约束条件(1)(2)的条件下,尽量靠前插入。并且,我们还约定,如果有多个空档可以插入,就在保证约束条件(1)(2)的条件下,插入到最前面的一个空档。于是,在这些约定下,上例中的方案一是正确的,而方案二是不正确的。显然,在这些约定下,对于给定的安排顺序,符合该安排顺序的实施方案是唯一的,请你计算出该方案完成全部任务所需的总时间。

格式

输入格式

输入文件的第1行为两个正整数,用一个空格隔开:
m n (其中m(<20)表示机器数,n(<20)表示工件数)
第2行:m*n个用空格隔开的数,为给定的安排顺序。
接下来的2n行,每行都是用空格隔开的m个正整数,每个数不超过20。
其中前n行依次表示每个工件的每个工序所使用的机器号,第1个数为第1个工序的机器号,第2个数为第2个工序机器号,等等。
后n行依次表示每个工件的每个工序的加工时间。
可以保证,以上各数据都是正确的,不必检验。

输出格式
输出文件只有一个正整数,为最少的加工时间。

样例1


样例输入

2 3
1 1 2 3 3 2
1 2
1 2
2 1
3 2
2 5
2 4

样例输出

10

思路

  • 并无特殊算法,题目较难理解(这是一道语文题)

代码


#include <stdio.h>
const int maxn = 25;
int a[maxn*maxn], ord[maxn][maxn], time[maxn][maxn];
int vis[maxn*maxn][maxn*maxn], b[maxn], finish[maxn];
//vis表示用过的区间,注意数组问题
inline int Max ( int a, int b )
{  return a > b ? a : b;
}
int main ( )
{  //注意最重要的一句话:  //同一个工件,每道工序必须在它前面的工序完成后才能开始  int n, m, ans;  //freopen ( "in0.in", "r", stdin );  //freopen ( "in0.out", "w", stdout );  scanf ( "%d%d", &m, &n );  for ( int i = 0; i < n*m; i ++ )  {  scanf ( "%d", &a[i] );  a[i] --;  }  for ( int i = 0; i < n; i ++ )  for ( int j = 0; j < m; j ++ )  {  scanf ( "%d", &ord[i][j] );  ord[i][j] --;  }  for ( int i = 0; i < n; i ++ )  for ( int j = 0; j < m; j ++ )  scanf ( "%d", &time[i][j] );  ans = 0;  for ( int i = 0; i < n*m; i ++ )  {  int t = a[i], j = b[t];  int pos = finish[t]-1, k, sub = ord[t][j];  //pos从此工序完成的起点-1开始,下面会加1  do  {  pos ++;  for ( k = 0; k < time[t][j]; k ++ )  if ( vis[sub][pos+k] )  {  pos = pos+k;  break ;  }  }while ( vis[sub][pos] );  for ( int l = pos; l < pos+time[t][j]; l ++ )  vis[sub][l] = 1;    //将这段区间标记  ans = Max ( ans, pos+time[t][j] );  //找到最大时间  finish[t] = pos+k;  //表示工序t完成需要的时间  b[t] ++;  }  printf ( "%d", ans );  return 0;
}

2^k进制数


原题

设r是个2k 进制数,并满足以下条件:

(1)r至少是个2位的2k 进制数。
(2)作为2k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位。
(3)将r转换为2进制数q后,则q的总位数不超过w。

在这里,正整数k(1≤k≤9)和w(k<w≤30000)是事先给定的。

问:满足上述条件的不同的r共有多少个?

我们再从另一角度作些解释:设S是长度为w 的01字符串(即字符串S由w个“0”或“1”组成),S对应于上述条件(3)中的q。将S从右起划分为若干个长度为k 的段,每段对应一位2k进制的数,如果S至少可分成2段,则S所对应的二进制数又可以转换为上述的2k 进制数r。

例:

设k=3,w=7。则r是个八进制数(23=8)。由于w=7,长度为7的01字符串按3位一段分,可分为3段(即1,3,3,左边第一段只有一个二进制位),则满足条件的八进制数有:

  1. 2位数:高位为1:6个(即12,13,14,15,16,17),高位为2:5个,…,高位为6:1个(即67)。共6+5+…+1=21个。
  2. 3位数:高位只能是1,第2位为2:5个(即123,124,125,126,127),第2位为3:4个,…,第2位为6:1个(即167)。共5+4+…+1=15个。

所以,满足要求的r共有36个。

输入输出

输入
输入文件digital.in只有1行,为两个正整数,用一个空格隔开:

  k  W

输出

输出文件digital.out为1行,是一个正整数,为所求的计算结果,即满足条件的不同的r的个数(用十进制数表示),要求最高位不得为0,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。

提示:作为结果的正整数可能很大,但不会超过200位)

样例

输入

3  7

输出

36

思路

题目中的那个从另一角度分析就已经蕴含了这个题的基本思路。就以题目的例子为例,长度为7位的01字串按3位一段就这样分:0 000 000。其中除了首段,每段都小于(111)2,也即小于2k,而首段自然是小于2w%k(对于w%k为0时也成立)了。

  1. 如果首段为0,则当这个2k进制数位数分别为2、3、…、[n/k]时,如果用b_max表示2k,对应的解的个数分别为C[b_max-1][2]、C[b_max-1][3]、…、C[b_max-1][n/k](C[i][j]表示从i个数里选j个构成一组组合)。

  2. 如果首段不为0,设首段为x,则解就有c[b_max-x-1][n/k]个。

这样,求解的个数就搞定了,剩下的活就是高精了。求组合数可以用这个公式:C[n][m]=C[n-1][m-1]+C[n-1][m],这样高精就只用加法了。

代码

#include<iostream>
using namespace std;
int k,n,bx,hx,ans[201];
int c[512][512][100];
void plus1(int x[],int y[],int z[])
{z[0]=max(x[0],y[0]);for(int i=1;i<=z[0];i++) {z[i]+=x[i]+y[i];z[i+1]+=z[i]/10;z[i]%=10;}if(z[z[0]+1]!=0)z[0]++;
}
void plus2(int x[],int y[])
{x[0]=max(x[0],y[0]);for(int i=1;i<=x[0];i++) {x[i]+=y[i];x[i+1]+=x[i]/10;x[i]%=10;}if(x[x[0]+1]!=0)x[0]++;
}
int main()
{cin>>k>>n;bx=1<<k;//2^khx=1<<(n%k);for(int i=0;i<=bx;i++)for(int j=0;j<=i;j++){if(j==0)c[i][j][0]=c[i][j][1]=1;else plus1(c[i-1][j],c[i-1][j-1],c[i][j]);}for(int i=2;i<=n/k&&i<bx;i++)plus2(ans,c[bx-1][i]);for(int i=1;i<hx&&n/k+i<bx;i++)plus2(ans,c[bx-i-1][n/k]);for(int i=ans[0];i>=1;i--)cout<<ans[i];cout<<endl;return 0;
}

转载于:https://www.cnblogs.com/bbqub/p/7599370.html

noip2006总结相关推荐

  1. P1064 [NOIP2006 提高组] 金明的预算方案

    P1064 [NOIP2006 提高组] 金明的预算方案 题意: 每个物品有价格和价值,物品之间存在依赖关系(单向的),现在又n元钱,买哪些物品,即满足依赖关系又使得每件物品的价格与价值的乘积的总和最 ...

  2. 信息学奥赛一本通 1844:【06NOIP提高组】金明的预算方案 | 洛谷 P1064 [NOIP2006 提高组] 金明的预算方案

    [题目链接] ybt 1844:[06NOIP提高组]金明的预算方案 洛谷 P1064 [NOIP2006 提高组] 金明的预算方案 [题目考点] 1. 动态规划:分组背包 2. 动态规划:依赖背包 ...

  3. 信息学奥赛一本通 1184 | 1934:【06NOIP普及组】明明的随机数 | OpenJudge NOI 1.10 09 | 洛谷 P1059 [NOIP2006 普及组] 明明的随机数

    [题目链接] ybt 1184:明明的随机数 ybt 1934:[06NOIP普及组]明明的随机数 OpenJudge NOI 1.10 09:明明的随机数 洛谷 P1059 [NOIP2006 普及 ...

  4. 信息学奥赛一本通 1937:【06NOIP普及组】数列 | 洛谷 P1062 [NOIP2006 普及组] 数列

    [题目链接] ybt 1937:[06NOIP普及组]数列 洛谷 P1062 [NOIP2006 普及组] 数列 [题目考点] 1. 数制 [解题思路] 如果k为2,那么这个数列 第1项为202^02 ...

  5. 洛谷——P1059 [NOIP2006 普及组] 明明的随机数

    P1059 [NOIP2006 普及组] 明明的随机数 题目描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了NN个11到10001000之间的随机整数(N≤100 ...

  6. 依赖背包dp NOIP2006 vijos 1313 金明的预算方案

    依赖背包: 简化的问题 这种背包问题的物品间存在某种"依赖"的关系.也就是说,物品i依赖于物品j,表示若选物品i,则必须选物品j.为了简化起见,我们先设没有某个物品既依赖于别的物品 ...

  7. 【背包DP练习】洛谷 P5020货币系统 P1757通天之分组背包 P1064[NOIP2006 提高组]金明的预算方案 P5322 [BJOI2019]排兵布阵

    洛谷 P5020货币系统 https://www.luogu.com.cn/problem/P5020 思路是把货币从小到大排序,然后按顺序依次完全背包dp,每次dp检查i-1种面值的货币能不能凑出第 ...

  8. noip2006 JAM计数法 (模拟)

    A1157. JAM计数法 时间限制:1.0s   内存限制:256.0MB   总提交次数:266   AC次数:158   平均分:65.23 将本题分享到:        查看未格式化的试题   ...

  9. 洛谷P1059 [NOIP2006 普及组] 明明的随机数

    题目链接: [NOIP2006 普及组] 明明的随机数 洛谷P1059 [NOIP2006 普及组] 明明的随机数 目录 洛谷P1059 [NOIP2006 普及组] 明明的随机数 1.题目 > ...

  10. [NOIP2006]明明的随机数

    [NOIP2006]明明的随机数 今天我们还是来点简单题,中等题和难题我们过两天再来分享哈,好了,我们一起来看看题意吧: 题目描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用 ...

最新文章

  1. dump文件的生成及的分析
  2. 用函数求10个数的平均值_Excel AVERAGEIF函数条件求平均值
  3. Matplotlib实例教程(十五) 3D散点图
  4. Linux运行Django项目远程访问时报错:Invalid HTTP_HOST header: '***.***.*.*:8000'.
  5. sublime text里添加对Gradle配置文件的支持
  6. 计算机网络怎么查看连接打印机驱动,如何检测网络打印机是否已成功连接到计算机[检测方法]...
  7. 分布式精华问答 | 如何实现分布式系统的高可用性?
  8. 数据结构上机实践第八周项目4-字符串加密
  9. 如何发送请求以及AJAX
  10. Caused by: java.lang.ClassNotFoundException: org.springframework.orm.hibernate4.HibernateTemplate
  11. 2012年2月份第1周51Aspx源码发布详情
  12. STM32 CAN波特率设置
  13. 基于matlab的车牌识别系统设计
  14. matlab 拉普拉斯求解,matlab解拉普拉斯方程.ppt
  15. 66个求职应聘技巧性问答(六)
  16. 治疗便秘的30种秘方
  17. win10操作系统创建局域网共享文件夹
  18. 论文笔记之:Playing for Data: Ground Truth from Computer Games
  19. java 中文大写金额_java编写的金额转中文大写
  20. 理解透彻!java微信公众号开发流程

热门文章

  1. php ajax轮询推送,[PHP]PHP+AJAX实现轮询代码
  2. capture one 20 pro中文版
  3. ECMAScript 6 入门
  4. [BZOJ2693]jzptab
  5. php is_null、empty、isset的区别
  6. 团队编程项目作业2-团队编程项目开发环境搭建过程
  7. Deepin下配置JDK8
  8. SQL点滴1—SET QUOTED_IDENTIFIER OFF语句的作用
  9. iOS 模型数组去重复
  10. 学习String的内容