晚上屯题系列

tonyfang posted @ 2015年8月30日 19:16 in 随笔 with tags c++ OI , 494 阅读

不能颓了,得复习NOIp

屯些题目吧,FZYZOJ

现在做了:

6

update: 2015/8/30 20:17 不屯了,第一次屯,屯炸了,好累~

1004:文科生的悲哀(Matrix67),简单递推。

1006:三取方格数,多线程DP。

 

# include <stdio.h>
# include <algorithm> 
using namespace std;
int f[44][22][22][22];
int n,a[22][22];
int main() {
	scanf("%d",&n);
	for (int i=1;i<=n;++i)
		for (int j=1;j<=n;++j)
			scanf("%d",&a[i][j]);
	//f[i,j,k,l] 走了i步,第一个人横着走了j步,第二个人横着走了k步,第三个人横着走了l步
	for (int i=1;i<=2*n;++i)
		for (int j=1;j<=i;++j)
			for (int k=1;k<=i;++k)
				for (int l=1;l<=i;++l) {
					int j2=i-j+1,k2=i-k+1,l2=i-l+1;
					f[i][j][k][l]=max(f[i-1][j][k][l], max(
					                  f[i-1][j-1][k][l], max(
					                  f[i-1][j-1][k][l-1], max(
					                  f[i-1][j-1][k-1][l], max(
					                  f[i-1][j-1][k-1][l-1], max(
					                  f[i-1][j][k][l-1], max(
					                  f[i-1][j][k-1][l], 
					                  f[i-1][j][k-1][l-1])))))));
					f[i][j][k][l]+=a[j][j2]+a[k][k2]+a[l][l2];
					if(j==k&&k==l) f[i][j][k][l]-=(a[j][j2]+a[k][k2]);
					else {
						if(j==k) f[i][j][k][l]-=a[j][j2];
						else if(k==l) f[i][j][k][l]-=a[k][k2];
						else if(j==l) f[i][j][k][l]-=a[l][l2];
					}						  
				} 
	printf("%d\n",f[2*n-1][n][n][n]); 
}

1016:三国杀1v1大赛:序列动态规划。$f[i,j]$表示前$i$次比赛,$j$个人的最小值。

需要滚动数组。

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int n,m,a[10003],i,now,last;
long long f[2][10003];
inline int cmp(int a,int b){return a>b;}
int main() {
	for(i=scanf("%d%d",&n,&m)-1;i<=m;++i) scanf("%d",&a[i]);
	sort(a+1,a+m+1,cmp);
	for(i=1,now=0,last=1;i<=n;++i) {
		now^=1,last^=1;
		memset(f[now],21444444,sizeof(f[now]));
		for (int j=3*i;j<=m;++j)
			f[now][j]=min(f[now][j-1],f[last][j-2]+1LL*(a[j]-a[j-1])*(a[j]-a[j-1]));
	} printf("%lld\n",f[now][m]);
}

 

1032:LCIS,经典DP,学了学,感觉很……

这题炖烂了……WA了几发,后来看了看,这是LCIS不是LIS,我写成了$a[i]!=b[j]$,………………

#include<stdio.h>
	#include<string.h> 
	using namespace std;
	int n,m1,m2,a[510],b[510],f[510]={},maxc=0;
	int main(){
		scanf("%d",&n);while(n--) {memset(f,0,sizeof(f));
			scanf("%d",&m1);for(int i=1;i<=m1;++i)scanf("%d",&a[i]);
			scanf("%d",&m2);for(int i=1;i<=m2;++i)scanf("%d",&b[i]);
			for(int i=1;i<=m1;++i){
				maxc=0;
				for(int j=1;j<=m2;++j) {
					if(a[i]>b[j]&&f[j]>maxc)maxc=f[j];
					if(a[i]==b[j])f[j]=maxc+1;
				}
			}
			maxc=0;
			for(int i=1;i<=m2;++i)if(f[i]>maxc)maxc=f[i];
			printf("%d\n",maxc);
		}
	}

2207:Zrn的骗分策略:背包变种。

 

#include<stdio.h>
#include<algorithm>
using namespace std;
int f[210][210],n,t,a[210][13];
//前i题,用了t分钟,最多骗分 
int main() {
	scanf("%d%d",&n,&t);
	for (int i=1;i<=n;++i)
		for(int j=1;j<=10;++j)scanf("%d",&a[i][j]);
	for (int i=1;i<=n;++i)
		for (int j=1;j<=t;++j) {
			f[i][j]=f[i][j-1];
			for(int k=0;k<=10;++k)
				if(j>=a[i][k])f[i][j]=max(f[i][j],f[i-1][j-a[i][k]]+k*10);
		}
	printf("%d\n",f[n][t]);
}

1282: NOIP福建夏令营最大和,求个最大子段和和最小子段和,答案就是max(最大子段和,总和-最小子段和)。

 

#include <stdio.h>
#define max(a,b) ((a)<(b)?(b):(a))
using namespace std;
int n,m1=-2147480000,m2=2147480000,g,x=0,y=0,t;
int main() {
    scanf("%d",&n);while(n--) {
        scanf("%d",&g);t+=g;
        if(x>0)x+=g;else x=g;
        if(y<0)y+=g;else y=g;
        if(x>m1)m1=x;
        if(y<m2)m2=y; 
    }
    printf("%d\n",max(m1,t-m2));
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter