19.05.09 解题报告

预计得分:100+50+100=250

实际得分:5+50+0=55

发下试题,看了一遍三个题:
T1 sb题、裸的背包
T2 我可以模拟。。
T3 sb题、贪心、优先队列

T1 多重背包

(backpack.cpp/c/pas)

(1s/256M)

题目描述

提供一个背包,它最多能负载重量为W的物品。
现在给出N种物品:对于第i类物品,一共有Ci件物品;对于每一件物品,重量为Wi,价值为Vi。
找出一种装载方式使得背包中的物品总价值最大。

输入格式(backpack.in)

第一行两个整数N,W,代表物品的种类与背包的总负重。
第2~N+1行,每行三个整数Wi, Vi, Ci,代表第i种物品的重量、价值与数量。

输出格式(backpack.out)

仅一行,一个整数V,代表最大的总价值。

样例输入

3 9
5 8 2
3 6 2
2 1 5

样例输出

14

数据范围与限制

1<=N<=20, 0<=W<=1000
1<=Wi<=100, 0<=Vi<=100, 0<=Ci<=100

我是真的服我自己,好好的多重背包不写,偏偏要逞能,写个多重转01背包,得个5分让自己乐呵乐呵???(我是**嘛??)

AC代码:

#include<iostream>
#include<cstdio>
using namespace std;

int N,W;

#define MAXN 1111

int w[MAXN],v[MAXN],c[MAXN];

inline int read() {
	int x=0,f=1;
	char c=getchar();
	for(; !isdigit(c); c=getchar()) if(c=='-') f=-1;
	for(;  isdigit(c); c=getchar()) x=x*10+c-'0';
	return x*f;
}

int f[MAXN];

int main() {
	freopen("backpack.in","r",stdin);
	freopen("backpack.out","w",stdout);
	cin>>N>>W;
	for(int i=1; i<=N; i++)
		cin>>w[i]>>v[i]>>c[i];
	for(int i=1; i<=N; i++)
		for(int j=1; j<=c[i]; j++)
			for(int k=W; k>=w[i]; k--)
				f[k]=max(f[k],f[k-w[i]]+v[i]);
	cout<<f[W];
	return 0;
}

T2 循环序列

(circulate.cpp/c/pas)

(1s/256M)

题目描述

Alice与Bob在玩游戏:
Alice首先给出两个数X与Y(X<=Y);
Bob则按顺序将X,X+1,X+2,…,Y-1,Y写成一个大数S。
Alice最后将S首尾相连,让其围成一个圈。
这时,Bob想知道,从S的开头出发,往后的第L位到第R位数字之和是多少。

输入格式(circulate.in)

第一行四个整数X,Y,L,R,代表Alice的两个数字和Bob想要知道的第L位到第R位的数字之和。

输出格式(circulate.out)

仅一行,一个整数M,代表第L位到第R位的数字之和。

样例输入

10 11 4 12

样例输出

7

样例解释

Bob将数字写成一行大数S = 1011;围成一个圈后,从第4位到第12位分别是1,1,0,1,1,1,0,1,1,它们的和是7.

数据范围与限制

对于50%的数据,L=1, X,Y,L,R<=1000;
对于100%的数据,S的长度不大于10000,X,Y,L,R<=100000000.

考试的时候,蹦出来的第一个思路是**模拟(记录+建环),看了眼数据范围,觉得很骚,但是又没有想到更好的,于是……

Code:(码风鬼畜)

#include<iostream>
#include<cstdio>
using namespace std;

#define N 100000011

char S[N];

int X,Y,L,R;

inline int read() {
	int x=0,f=1;
	char c=getchar();
	for(; !isdigit(c); c=getchar()) if(c=='-') f=-1;
	for(;  isdigit(c); c=getchar()) x=x*10+c-'0';
	return x*f;
}

int cnt=0;

int ans=0;

int main(void) {
	freopen("circulate.in","r",stdin);
	freopen("circulate.out","w",stdout);
	X=read();
	Y=read();
	L=read();
	R=read();
	for(int i=X; i<=Y; i++) {
		if((i/10)==0) {
			S[cnt++]=(char)i;
		} else if((i/10<10) && (i/10>0)) {
			S[cnt++]=(char)(i/10);
			S[cnt++]=(char)(i%10);
		} else if((i/100<10) && (i/100>0)) {
			S[cnt++]=(char)(i/100);
			S[cnt++]=(char)(i%100/10);
			S[cnt++]=(char)(i%10);
		} else if((i/1000<10) && (i/1000>0)) {
			S[cnt++]=(char)(i/1000);
			S[cnt++]=(char)(i%1000/100);
			S[cnt++]=(char)(i%100/10);
			S[cnt++]=(char)(i%10);
		} else if((i/10000<10) && (i/10000>0)) {
			S[cnt++]=(char)(i/10000);
			S[cnt++]=(char)(i%10000/1000);
			S[cnt++]=(char)(i%1000/100);
			S[cnt++]=(char)(i%100/10);
			S[cnt++]=(char)(i%10);
		} else if((i/100000<10) && (i/100000>0)) {
			S[cnt++]=(char)(i/100000);
			S[cnt++]=(char)(i%100000/10000);
			S[cnt++]=(char)(i%10000/1000);
			S[cnt++]=(char)(i%1000/100);
			S[cnt++]=(char)(i%100/10);
			S[cnt++]=(char)(i%10);
		} else if((i/1000000<10) && (i/1000000>0)) {
			S[cnt++]=(char)(i/1000000);
			S[cnt++]=(char)(i%1000000/100000);
			S[cnt++]=(char)(i%100000/10000);
			S[cnt++]=(char)(i%10000/1000);
			S[cnt++]=(char)(i%1000/100);
			S[cnt++]=(char)(i%100/10);
			S[cnt++]=(char)(i%10);
		} else if((i/10000000<10) && (i/10000000>0)) {
			S[cnt++]=(char)(i/10000000);
			S[cnt++]=(char)(i%10000000/1000000);
			S[cnt++]=(char)(i%1000000/100000);
			S[cnt++]=(char)(i%100000/10000);
			S[cnt++]=(char)(i%10000/1000);
			S[cnt++]=(char)(i%1000/100);
			S[cnt++]=(char)(i%100/10);
			S[cnt++]=(char)(i%10);
		} else if((i/100000000<10) && (i/100000000>0)) {
			S[cnt++]=(char)(i/100000000);
			S[cnt++]=(char)(i%100000000/10000000);
			S[cnt++]=(char)(i%10000000/1000000);
			S[cnt++]=(char)(i%1000000/100000);
			S[cnt++]=(char)(i%100000/10000);
			S[cnt++]=(char)(i%10000/1000);
			S[cnt++]=(char)(i%1000/100);
			S[cnt++]=(char)(i%100/10);
			S[cnt++]=(char)(i%10);
		}
	}
	int opt=cnt-1;
	for(int i=0; i<cnt; i++) {
		S[++opt]=S[i];
	}//2
	for(int i=0; i<2*cnt; i++) {
		S[++opt]=S[i];
	}//4
	for(int i=0; i<4*cnt; i++) {
		S[++opt]=S[i];
	}//8
	for(int i=0; i<8*cnt; i++) {
		S[++opt]=S[i];
	}//16
	for(int i=0; i<16*cnt; i++) {
		S[++opt]=S[i];
	}//32
	for(int i=0; i<32*cnt; i++) {
		S[++opt]=S[i];
	}//64
	for(int i=0; i<64*cnt; i++) {
		S[++opt]=S[i];
	}//128
	for(int i=0; i<128*cnt; i++) {
		S[++opt]=S[i];
	}//256
	for(int i=0; i<256*cnt; i++) {
		S[++opt]=S[i];
	}//512
	for(int i=0; i<512*cnt; i++) {
		S[++opt]=S[i];
	}//1024
	for(int i=L-1; i<R; i++) {
		ans+=(int)S[i];
	}
	cout<<ans;
	/*	for(int i=2*opt;i>=opt+1;i--){
			S[i]=
		}*/
	/*	for(int i=1; i<=cnt; i++)
			cout<<(int)S[i]<<"
";*/
	return 0;
}

不过考试的时候,看见坐在我旁边的cgp Dalao一直在咳咳(面露微笑)。阔怕阔怕~隐隐约约还听到他忽然叫了一句:我想到优化了!!(果然,我太菜了)

AC代码:

#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>

using namespace std;

#define N 100011

#define LL long long int

stack<int>S;

int a[N];

int cnt=0;

LL x,y,l,r,k;

LL ans=0,sum=0;

int main(void) {
	freopen("circulate.in","r",stdin);
	freopen("circulate.out","w",stdout);
	cin>>x>>y>>l>>r;
	while(x<=y) {
		k=x;
		while(k!=0) {
			S.push(k%10);
			k=k/10;
		}
		while(!S.empty()) {
			cnt++;
			a[cnt]=S.top();
			S.pop();
		}
		x++;
	}
	int flag=0;
	sum=1;
	for(int i=1; i<=cnt+1; i++) {
		if(i==cnt+1) i=1;
		if(sum==l) {
			flag=1;
		}
		if(flag)
			ans+=a[i];
		sum++;
		if(sum==r+1) break;
	}
	cout<<ans;
	return 0;
}

T3合并游戏

merge.cpp/c/pas

(1s/256M)

题目描述

Cindy和Dan在玩一个游戏。
一开始Cindy想出了N个数,接着她把这N个数全部给了Dan。

Dan得到这组数后,它会挑出3个数(如果不足3个则全部挑出)。Dan会把这几个数加起来变成一个数,然后再把这个数与剩下的数再放到一起。Dan会一直这样做,直到最后只剩下一个数。

Cindy则会在旁边记下每次Dan得到的数,她把这些数加起来,作为本次游戏的得分。她想知道,对于一组数,Dan能得到的最大的得分是多少?

输入格式

第一行一个正整数N,代表这组数的个数;
第二行N个正整数,代表这N个整数。

输出格式

一行一个整数,代表可能的最大得分。

样例输入(merge.in)

4
3 1 5 6

样例输出(merge.out)

29

样例解释

Dan可以首先把(3,5,6)这三个数先合并起来,得到3 + 5 +6 = 14;接着他把剩下的两个数再合起来,得到1+14=15.这样,总得分是最大的 14 + 15 = 29.

数据范围与限制

对于50%的数据,N<=10
对于100%的数据,N<=1000,所有数不大于1000

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define N 1111

int n;

int a[N];

int ans=0;

int opt=0;

int main(void) {
	freopen("merge.in","r",stdin);	
	freopen("merge.out","w",stdout);	
	priority_queue<int> Q;//大头堆
	cin>>n;
	for(int i=1; i<=n; i++) {
		cin>>a[i];
		Q.push(a[i]);
	}
	if(n<=3) {
		for(int i=1; i<=n; i++) ans+=a[i];
		cout<<ans;
		return 0;
	} else {
		ans+=Q.top();
		Q.pop();//1
		ans+=Q.top();
		Q.pop();//2
		ans+=Q.top();
		Q.pop();//3
		Q.push(ans);
		int uxv=0;
		while(Q.size()>3) {
			for(int i=1; i<=3; i++) {
				uxv+=Q.top();
				Q.pop();
			}
			ans+=uxv;
			Q.push(uxv);
			uxv=0;
		}
		uxv=0;
		if(Q.size()<=3) {
			while(!Q.empty()) {
				uxv+=Q.top();
				Q.pop();
			}
			ans+=uxv;
		}
		cout<<ans;
		return 0;
	}
}

综合而言:这次考试我真的**了。

原文地址:https://www.cnblogs.com/morbidity/p/10841169.html