某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于等于前一发的高度。某天,雷达捕捉到敌国导弹来袭。由于该系统还在试用阶段,所以只用一套系统,因此有可能不能拦截所有的导弹。
2 8 389 207 155 300 299 170 158 65 3 88 34 65
6 2
#include
using namespace std;
int main()
{
int t,n,a[20],dp[20];
cin>>t;
while(t--)
{
int maxx=-1;
cin>>n;
for (int i=0; i>a[i];
fill(dp,dp+20,1);
for (int i=0; ia[i])
{
dp[i]=max(dp[i],dp[j]+1);
if(dp[i]>maxx)
maxx=dp[i];
}
cout<
17-单调递增最长子序列
内存限制:64MB
时间限制:3000ms
Special Judge: No
accepted:4
submit:8
题目描述:
求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4
输入描述:
第一行一个整数0
输出描述:
输出字符串的最长递增子序列的长度
样例输入:
复制
3
aaa
ababc
abklmncdefg
样例输出:
1
3
7
题解:状态转移方程:dp[i]=max(dp[j]), dp[j]
#include
using namespace std;
int main()
{
int t,dp[10001];
string str;
cin>>t;
while(t--)
{
int maxx=1;
cin>>str;
fill(dp,dp+10001,1);
for (int i=0; i
37-回文字符串
内存限制:64MB
时间限制:3000ms
Special Judge: No
accepted:2
submit:3
题目描述:
所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba"。当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串。现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串。
输入描述:
第一行给出整数N(0
输出描述:
每行输出所需添加的最少字符数
样例输入:
复制
1
Ab3bd
样例输出:
2
题解:求最长公共子序列。添加字符=原串长-最长公共子序列长。
dp[i][j]表示长为i的s1前缀和长为j的s2前缀的最长公共子序列长。
状态转移方程:s1[i]==s2[j] dp[i][j]=dp[i-1][j-1]+1;
s1!=s2[j] dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
#include
#include
using namespace std;
int dp[1001][1001];
int main()
{
int t;
string s1,s2;
cin>>t;
while(t--)
{
cin>>s1;
int len=s1.size();
s2=s1;
reverse(s2.begin(),s2.end());
fill(dp[0],dp[0]+(len+1)*(len+1),0);
for (int i=0;i
阅读量:238
104-最大和
内存限制:64MB
时间限制:1000ms
Special Judge: No
accepted:2
submit:3
题目描述:
给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。
例子:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩阵为:
9 2
-4 1
-1 8
其元素总和为15。
输入描述:
第一行输入一个整数n(0
输出描述:
输出矩阵的最大子矩阵的元素之和。
样例输入:
复制
1
4 4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
样例输出:
15
题解:将二维压缩成一维,然后转化为求最大子串和。
#include
using namespace std;
int main ()
{
int t,n,m,a[101][101];
cin>>t;
while(t--)
{
cin>>n>>m;
fill(a[0],a[0]+101*101,0);
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
{
cin>>a[i][j];
a[i][j]+=a[i-1][j];//求第j列的前i项和。
}
int mx=a[1][1];
for (int i=1; i<=n; i++)
for (int j=i; j<=n; j++)
{
int sum=0;
for (int k=1; k<=m; k++)
{
int tmp=a[j][k]-a[i-1][k];
sum=(sum>=0?sum:0)+tmp;
mx=max(mx,sum);
}
}
cout<
325-zb的生日
内存限制:64MB
时间限制:3000ms
Special Judge: No
accepted:4
submit:11
题目描述:
今天是阴历七月初五,acm队员zb的生日。zb正在和C小加、never在武汉集训。他想给这两位兄弟买点什么庆祝生日,经过调查,zb发现C小加和never都很喜欢吃西瓜,而且一吃就是一堆的那种,zb立刻下定决心买了一堆西瓜。当他准备把西瓜送给C小加和never的时候,遇到了一个难题,never和C小加不在一块住,只能把西瓜分成两堆给他们,为了对每个人都公平,他想让两堆的重量之差最小。每个西瓜的重量已知,你能帮帮他么?
输入描述:
多组测试数据(<=1500)。数据以EOF结尾 第一行输入西瓜数量N (1 ≤ N ≤ 20) 第二行有N个数,W1, …, Wn (1 ≤ Wi ≤ 10000)分别代表每个西瓜的重量
输出描述:
输出分成两堆后的质量差
样例输入:
复制
5
5 8 13 27 14
样例输出:
3
题解:若想两部分尽量相等,那么只要考虑一个部分,让它接近它们总和的一半。
dp[j]表示重量为j能否凑成,当然j最大为sum/2。
状态转移方程:if(dp[j-w[i]]==1)dp[j]=dp[j-w[i]]。
#include
int dp[100001];
using namespace std;
int main ()
{
int n,w[21],m,sum;
while(cin>>n)
{
m=sum=0;
fill(dp,dp+100001,0);
for (int i=0; i>w[i];
sum+=w[i];
}
dp[0]=1;
for (int i=0; i=w[i]; j--)
if(dp[j-w[i]])
dp[j]=1;
}
int i;
for (i=sum/2;!dp[i];i--);//找出最接近sum/2的重量。
cout<
168-房间安排
内存限制:64MB
时间限制:3000ms
Special Judge: No
accepted:8
submit:19
题目描述:
2010年上海世界博览会(Expo2010),是第41届世界博览会。于2010年5月1日至10月31日期间,在中国上海市举行。本次世博会也是由中国举办的首届世界博览会。上海世博会以“城市,让生活更美好”(Better City,Better Life)为主题,将充分探索21世纪城市生活。
这次世博会总投资达450亿人民币,创造了世界博览会史上的最大规模记录。吸引200个国家和国际组织参展。预计有7000万人次的参观者。
为了更好地接待在这期间来自世界各地的参观者,如何合理安排各宾馆的住房问题提到了日程。组委会已接到了大量的客户住宿定单,每张定单的内容包括要住宿的房间数,开始住宿时间和要住的天数。为了便于整个城市各宾馆的管理,组委会希望对这些定单进行安排,目的是用尽可能少的房间来满足这些定单,以便空出更多的房间用于安排流动游客。
组委会请求DR.Kong来完成这个任务,对这些定单进行合理安排,使得满足这些定单要求的房间数最少。
假设:某个定单上的游客一旦被安排到某房间,在他预定住宿的期间内是不换房间的。为了简化描述,定单上的开始住宿时间为距离现在的第几天。例如,定单为(10,30,5)表示游客要求使用10个房间,第30天开始连住5天。
输入描述:
第一行:T 表示有T组测试数据 每组测试数据第一行:N 表示定单数 每组测试数据接下来有N行,每行有三个整数 A B C 表示房间数,开始住宿时间和天数 1<=T<=100 1<=N<=10000 1<=A<=10 1<=B<=180 1<=c<=10
输出描述:
输出一个整数,为满足所有定单要求的最少房间数。
样例输入:
复制
1
3
3 10 4
4 9 3
3 12 6
样例输出:
7
题解:定向思维了,开始以为是稍微复杂的贪心。其实只要在对应的区间进行叠加。
#include
using namespace std;
int s[200];
int main ()
{
int t;
cin>>t;
while(t--)
{
fill(s,s+200,0);
int n,maxx=-1;
cin>>n;
for (int i=0;i>a>>b>>c;
for (int j=b;jmaxx)
maxx=s[j];
}
}
cout<
311-完全背包
内存限制:64MB
时间限制:4000ms
Special Judge: No
accepted:1
submit:1
题目描述:
直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的体积是c,价值是w。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。本题要求是背包恰好装满背包时,求出最大价值总和是多少。如果不能恰好装满背包,输出NO
输入描述:
第一行: N 表示有多少组测试数据(N<7)。 接下来每组测试数据的第一行有两个整数M,V。 M表示物品种类的数目,V表示背包的总容量。(0
输出描述:
对应每组测试数据输出结果(如果能恰好装满背包,输出装满背包时背包内物品的最大价值总和。 如果不能恰好装满背包,输出NO)
样例输入:
复制
2
1 5
2 2
2 5
2 2
5 1
样例输出:
NO
1
题解:模板,由于要刚好装满,所以除dp[0]=0,其他的都赋值很小的负数。
#include
using namespace std;
int dp[50005],inf=0x3f3f3f3f;
int main ()
{
int t;
cin>>t;
while(t--)
{
fill(dp,dp+50005,-inf);
dp[0]=0;
int m,V,w[2001],v[2001];
cin>>m>>V;
for (int i=0;i>w[i]>>v[i];
for (int i=0;i0)
cout<
737-石子合并(一)
内存限制:64MB
时间限制:1000ms
Special Judge: No
accepted:1
submit:1
题目描述:
有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
输入描述:
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出描述:
输出总代价的最小值,占单独的一行
样例输入:
复制
3
1 2 3
7
13 7 8 16 21 4 18
样例输出:
9
239
题解:dp[i][j]表示:i到j合并总代价最小。dp[i][j]=min(dp[i][k]+dp[k+1][j]+i到j合并代价),i<=k
#include
using namespace std;
const int inf=0x3f3f3f3f;
int dp[201][201],sum[201];
int main ()
{
int n,m;
while(cin>>n)
{
sum[0]=0;
for (int i=1; i<=n; i++)
{
cin>>m;
sum[i]=sum[i-1]+m;
dp[i][i]=0;//不能合并
}
for (int len=1; len