1.NOI 最大子矩阵

1:最大子矩阵

总时间限制: 
1000ms

内存限制: 
65536kB
描述
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵。

比如,如下4 * 4的矩阵

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

的最大子矩阵是

9 2
-4 1
-1 8

这个子矩阵的大小是15。

输入
输入是一个N * N的矩阵。输入的第一行给出N (0 < N <= 100)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[-127, 127]。
输出
输出最大子矩阵的大小。
样例输入
4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1 8 0 -2
样例输出
15
来源
翻译自 Greater New York 2001 的试题
一般做法:N^3时间复杂度
/*方法:枚举每一行所有的区间情况,把这个区间从第一列向下加,加的过程中注意:因为有负数,所以如果之前加的和<0了,我们要舍弃之前的所有结果,重新开始新的矩阵,而且要注意对于ans的更新是在加的过程更新,因为随时有可能加上负数,虽然sum>0,所以加一次都要更新*/
#include<iostream>
using namespace std;
#include<cstdio>
const int N=;
const int INF=<<;
int n,a[N][N];
int main()
{
scanf("%d",&n);
int x;
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
{
scanf("%d",&x);
a[i][j]=a[i][j-]+x;
}
int ans=-INF;
for(int i=;i<=n;++i)
for(int j=i;j<=n;++j)
{
int tmp=;
for(int k=;k<=n;++k)
{
int num=a[k][j]-a[k][i-];
if(tmp>) tmp+=num;
else tmp=num;
if(tmp>ans) ans=tmp;
}
}
printf("%d\n",ans);
return ;
}

2.NOI 6047:分蛋糕

6047:分蛋糕

总时间限制: 
1000ms

内存限制: 
65536kB
描述

有一块矩形大蛋糕,长和宽分别是整数w 、h。现要将其切成m块小蛋糕,每个小蛋糕都必须是矩形、且长和宽均为整数。切蛋糕时,每次切一块蛋糕,将其分成两个矩形蛋糕。请计算:最后得到的m块小蛋糕中,最大的那块蛋糕的面积下限。

假设w= 4, h= 4, m= 4,则下面的切法可使得其中最大蛋糕块的面积最小。

假设w= 4, h= 4, m= 3,则下面的切法会使得其中最大蛋糕块的面积最小:

输入
共有多行,每行表示一个测试案例。每行是三个用空格分开的整数w, h, m ,其中1 ≤ w, h, m ≤ 20 , m ≤ wh. 当 w = h = m = 0 时不需要处理,表示输入结束。
输出
每个测试案例的结果占一行,输出一个整数,表示最大蛋糕块的面积下限。
样例输入
4 4 4
4 4 3
0 0 0
样例输出
4
6
代码:
/*这个题和之前做的那个棋盘分割很像,但是又有些不同,棋盘分割要求确定每一个矩形。
而在这个题目中,只要矩形的长宽还有切割的次数确定了,无论这个面积的矩形位于大矩形的什么地方,结果都是相同的,那就没有必要固定矩形位置,仅仅固定矩形的大小就可以了
第一次做,我用的就是确定矩形的位置,开了一个五维数组,结果全部超时,虽然样例过了。
f[i][j][k]表示的是i*j这个矩形分割为k份的最大面积的下限。
*/
#include<iostream>
using namespace std;
#include<cstdio>
#define N 21
int f[N][N][N];
int n,m,k;
#include<cstring>
void DP()
{
/*第一次的超时做法*/
/*for(int kk=1;kk<=k;++kk)
for(int x1=0;x1<=n;++x1)
for(int y1=0;y1<=m;++y1)
for(int x2=x1+1;x2<=n;++x2)
for(int y2=y1+1;y2<=m;++y2)
{
if(f[x1][y1][x2][y2][kk]<5000)
continue;
if(kk==1)
{
f[x1][y1][x2][y2][kk]=(x2-x1)*(y2-y1);
continue;
}
for(int x=x1+1;x<x2;++x)
{
f[x1][y1][x2][y2][kk]=min(max(f[x1][y1][x][y2][1],f[x][y1][x2][y2][kk-1]),f[x1][y1][x2][y2][kk]);
f[x1][y1][x2][y2][kk]=min(max(f[x1][y1][x][y2][kk-1],f[x][y1][x2][y2][1]),f[x1][y1][x2][y2][kk]);
}
for(int y=y1+1;y<y2;++y)
{
f[x1][y1][x2][y2][kk]=min(max(f[x1][y1][x2][y][1],f[x1][y][x2][y2][kk-1]),f[x1][y1][x2][y2][kk]);
f[x1][y1][x2][y2][kk]=min(max(f[x1][y1][x2][y][kk-1],f[x1][y][x2][y2][1]),f[x1][y1][x2][y2][kk]);
}
}*/ for(int kk=;kk<=k;++kk)
for(int x1=;x1<=n;++x1)
for(int y1=;y1<=m;++y1)
{
if(f[x1][y1][kk]<)/*记忆化搜索因为输入有多组数据,而且只要i,j,k确定,结果就不变,所以没有必要重复计算*/
continue;
if(kk==)
{
f[x1][y1][kk]=x1*y1;/*DP的初始化*/
continue;
}
for(int x=;x<x1;++x)
{
/* f[x1][y1][kk]=min(max(f[x][y1][kk-1],(x1-x)*y1),f[x1][y1][kk]);*/
/*f[x1][y1][kk]=min(max(x*y1,f[x1-x][y1][kk-1]),f[x1][y1][kk]);*/
for(int p=;p<kk;p++)
f[x1][y1][kk]=min(f[x1][y1][kk],max(f[x][y1][p],f[x1-x][y1][kk-p]));
/*这里与棋盘分割的不同,棋盘分割是上面的方程,因为棋盘分割要求“将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,”,所以必须是一块k-1份,一块1份才可以,
而这个“分蛋糕”只要求蛋糕是矩形,没要求每切一份,剩下的也是矩形*/
}
for(int y=;y<y1;++y)
{
/*f[x1][y1][kk]=min(max(f[x1][y][kk-1],x1*(y1-y)),f[x1][y1][kk]);*/
/* f[x1][y1][kk]=min(max(x1*y,f[x1][y1-y][kk-1]),f[x1][y1][kk]);*/
for(int p=;p<kk;p++)
f[x1][y1][kk]=min(f[x1][y1][kk],max(f[x1][y][p],f[x1][y1-y][kk-p]));
}
} }
int main()
{
memset(f,,sizeof(f));
while(scanf("%d%d%d",&n,&m,&k)==&&n&&m&&k)
{
DP();
printf("%d\n",f[n][m][k]);
}
return ;
}

3. NOI  6049:买书

6049:买书

总时间限制: 
1000ms

内存限制: 
65536kB
描述

小明手里有n元钱全部用来买书,书的价格为10元,20元,50元,100元。

问小明有多少种买书方案?(每种书可购买多本)

输入
一个整数 n,代表总共钱数。(0 <= n <= 1000)
输出
一个整数,代表选择方案种数
样例输入
样例输入1:
20 样例输入2:
15 样例输入3:
0
样例输出
样例输出1:
2 样例输出2:
0 样例输出3:
0
代码:
/*变形版的“线段覆盖”,把餐馆向后扩展k长度,作为一个线段就可以了*/
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#define N 101
int t,n,k,f[N];
struct Poi{
int l,r,val;
// bool operator <(const Poi &a)
// const { return r<a.r;}
};
Poi poi[N];
#include<algorithm>
void input()
{
memset(f,,sizeof(f));
memset(poi,,sizeof(poi));
scanf("%d%d",&n,&k);
for(int i=;i<=n;++i)
{
scanf("%d",&poi[i].l);
poi[i].r=poi[i].l+k;
}
for(int i=;i<=n;++i)
scanf("%d",&poi[i].val);
}
int ans=;
void DP()
{ // sort(poi+1,poi+n+1);
for(int i=;i<=n;++i)
f[i]=poi[i].val;
for(int i=;i<=n;++i)
{
for(int j=;j<i;++j)
{
if(poi[i].l>poi[j].r)
f[i]=max(f[i],f[j]+poi[i].val);
} }
}
int main()
{
scanf("%d",&t);
while(t--)
{
input();
DP();
ans=;
for(int i=;i<=n;++i)
ans=max(ans,f[i]);/*一开始犯了一个非常傻逼的错误,在DP中寻找f[i]的最大值,结果漏了f[1]恰好输入的数据有的就是仅仅建立第一个餐馆的利润最大,结果WA了*/
printf("%d\n",ans);
}
return ;
}
4. NOI 4978:宠物小精灵之收服

4978:宠物小精灵之收服

总时间限制: 
1000ms

内存限制: 
65536kB
描述

宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事。

一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵。小智也想收服其中的一些小精灵。然而,野生的小精灵并不那么容易被收服。对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,野生小精灵也会对皮卡丘造成一定的伤害(从而减少皮卡丘的体力)。当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也不会被小智收服。当小智的精灵球用完时,狩猎也宣告结束。

我们假设小智遇到野生小精灵时有两个选择:收服它,或者离开它。如果小智选择了收服,那么一定会扔出能够收服该小精灵的精灵球,而皮卡丘也一定会受到相应的伤害;如果选择离开它,那么小智不会损失精灵球,皮卡丘也不会损失体力。

小智的目标有两个:主要目标是收服尽可能多的野生小精灵;如果可以收服的小精灵数量一样,小智希望皮卡丘受到的伤害越小(剩余体力越大),因为他们还要继续冒险。

现在已知小智的精灵球数量和皮卡丘的初始体力,已知每一个小精灵需要的用于收服的精灵球数目和它在被收服过程中会对皮卡丘造成的伤害数目。请问,小智该如何选择收服哪些小精灵以达到他的目标呢?

输入
输入数据的第一行包含三个整数:N(0 < N < 1000),M(0 < M < 500),K(0 < K < 100),分别代表小智的精灵球数量、皮卡丘初始的体力值、野生小精灵的数量。
之后的K行,每一行代表一个野生小精灵,包括两个整数:收服该小精灵需要的精灵球的数量,以及收服过程中对皮卡丘造成的伤害。
输出
输出为一行,包含两个整数:C,R,分别表示最多收服C个小精灵,以及收服C个小精灵时皮卡丘的剩余体力值最多为R。
样例输入
样例输入1:
10 100 5
7 10
2 40
2 50
1 20
4 20 样例输入2:
10 100 5
8 110
12 10
20 10
5 200
1 110
样例输出
样例输出1:
3 30 样例输出2:
0 100
提示
对于样例输入1:小智选择:(7,10) (2,40) (1,20) 这样小智一共收服了3个小精灵,皮卡丘受到了70点伤害,剩余100-70=30点体力。所以输出3 30
对于样例输入2:小智一个小精灵都没法收服,皮卡丘也不会收到任何伤害,所以输出0 100
代码:
/*一个普通的二维01背包,注意体力不能是0,就可以了,
f[j][k]表示在使用了j个球,收到k点伤害的最大捕捉数目。
ans最好DP中更新,因为DP结束以后,最优值可能存在很多位置,伤害和球的数目不一定恰好用完
*/
#include<iostream>
using namespace std;
#include<cstdio>
#define N 1001
#define M 501
int n,m,k;
struct Jl{
int qiu,dam;
};
Jl jl[];
struct Ans{
int sum,tl;
};
Ans ans;
int f[N][M];
void input()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=k;++i)
{
scanf("%d%d",&jl[i].qiu,&jl[i].dam);
}
}
void DP()
{
ans.sum=;
ans.tl=m;
for(int i=;i<=k;++i)
for(int j=n;j>=jl[i].qiu;--j)
for(int k=m-;k>=jl[i].dam;--k)
{
f[j][k]=max(f[j][k],f[j-jl[i].qiu][k-jl[i].dam]+);
if((f[j][k]>ans.sum)||(f[j][k]==ans.sum&&(m-k)>ans.tl))
{
ans.sum=f[j][k];
ans.tl=m-k;
}
}
}
int main()
{
input();
DP();
printf("%d %d\n",ans.sum,ans.tl);
return ;
}

2016.4.9 NOI codevs动态规划专练的更多相关文章

  1. 2016. 4.10 NOI codevs 动态规划练习

    1.codevs1040 统计单词个数 1040 统计单词个数 2001年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 De ...

  2. 10-19 dp专练

    dp专练,终于克服了一次自己对dp的恐惧,磕出来一道题. 得分情况: T1:0 T2:0 T3:0 emmmm,磕出来的题是T2,但是因为初始化和int long long的原因爆零了 T1:n只狼排 ...

  3. P1251 递推专练3

    递推专练3 描述 Description 圆周上有N个点.连接任意多条(可能是0条)不相交的弦(共用端点也算相交)共有多少种方案? 输入格式 Input Format 读入一个数N.<=N< ...

  4. 2016.4.3 动态规划NOI专练 王老师讲课整理

    1.6049:买书 总时间限制:  1000ms 内存限制:  65536kB 描述 小明手里有n元钱全部用来买书,书的价格为10元,20元,50元,100元. 问小明有多少种买书方案?(每种书可购买 ...

  5. dp专练

    dp练习. codevs 1048 石子归并 区间dp #include<cstdio> #include<algorithm> #include<cstring> ...

  6. 2016.11.17 NOI plus day0

    今天很乱乱乱乱 根本不想写代码 玩了一早上了 昨晚失眠了 今天又懵逼了 中午就要走了 明天就要考试了 考完试回来就要补文化课了 现在我的内心很平静 因为已经紧张的冻结了 你知道什么叫彷徨么? 机房里的 ...

  7. 8.1搜索专练DFS和BFS

    这是第一次全部做出来的依次练习了,有一些都是做过两遍了的,但是还是错了几回,更多时候我还是应该多注意下细节,就好像章爷笑我 的一样,像什么vis[]标记没清0,什么格式错误,还有什么题目没看清,还是的 ...

  8. Contest 7.21(贪心专练)

    这一次都主要是贪心练习 练习地址http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26733#overview Problem APOJ 13 ...

  9. contest7.20(暴力专练)

    此次练习的地址:  http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26732#overview 密码 acmore Problem A(P ...

随机推荐

  1. ubuntu 提速

    linux的各大发行版,都有些不必要的服务被默认开启了,针对ubuntu,我们可以采用选择性关闭的方法加速起动,提高系统性能. 这里我们安装一个软件: sudo apt-get install sys ...

  2. AGC025简要题解

    AGC025简要题解 B RGB Coloring 一道简单题,枚举即可. C Interval Game 考虑可以进行的操作只有两种,即左拉和右拉,连续进行两次相同的操作是没有用的. 左拉时肯定会选 ...

  3. linux arm的存储分布那些事之一

    转自:http://blog.csdn.net/xiaojsj111/article/details/11724081   linux arm 内存分布总览   上图是linux的arm的虚拟地址分布 ...

  4. 终于解决了Linux下运行OCCI程序一直报Error while trying to retrieve text for error ORA-01804错误

    终于解决了Linux下运行OCCI程序一直报Error while trying to retrieve text for error ORA-01804错误 http://blog.csdn.net ...

  5. 12-6 NSArray

    原文:http://rypress.com/tutorials/objective-c/data-types/nsarray NSArray NSArray 是 Objective-C中最常用的数组类 ...

  6. tomcat远程调试参数备忘

    tomcat远程调试,启动时添加参数: -server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,ser ...

  7. 查看及连接指定 docker container

    环境: 1.centos7 2.以root身份登录 3.已安装docker并且运行着一个container A.查看正在运行的container docker ps 效果: B.查看本地所有conta ...

  8. Linux下cp命令的使用说明

    [root@www ~]# cp [-adfilprsu] 来源档(source) 目标档(destination)[root@www ~]# cp [options] source1 source2 ...

  9. CentOS7.5下gnome-terminal+vim的solarized配色方案

    1.简介 Solarized是一款包括浅色和深色的配色方案,适用于很多应用,可以让你的应用看起来更加漂亮!官网地址:http://ethanschoonover.com/solarized 2.设置g ...

  10. Java Control Statements

    Java Control Statements Java For Loop public class ForExample1 { public static void main(String[] ar ...