前言
突然就考試,做完1,2題就開始浪了。於是就第三題打了個暴力…
用Emacs之後代碼縮進似乎就呵呵了…
操練(Training.pas/c/cpp Time:1s Memory:256M
【問題描述】
高老大有一個
爲了維護世界的和平,爲了貫徹和平與發展的原則,老大不得不開始操練部下了。部下們必須站在廣場中某沒種上樹個格子中,而且一個格子內不允許有兩個人站着。同時,爲了顯得整齊劃一,部下們要維護一個方陣的陣型,也就是N*N的廣場內的一個
【輸入】
輸入文件名爲Training.in。
輸入第一行兩個正整數N和M,代表廣場的長和寬。
下接一個N行M列的字符矩陣,若第I行第J列爲‘0’則代表該格子上有一顆樹。
【輸出】
輸出文件名爲Training.out。
輸出一次最多能夠操練的部下個數。
【輸入輸出樣例】
Training.in
2
11
11
Training.out
4
【數據範圍】
對於80%的數據,
對於100%的數據,
【題解】
這道題目就是極大化子矩形 的一個模板吧,所以還好做吧。
這個題目的母題是USACO中的rectbarn,裏面講的很詳細。
解釋一下我這裏
【代碼】
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
const int size = 1000+10;
int n,ans;
int f[size][size];
char ch[size][size];
int minn,cnt;
inline int read() {
int f=1,in=0;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())
if(ch=='-')
f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())
in=in*10+ch-'0';
return in*f;
}
int main() {
freopen("training.in","r",stdin);
freopen("training.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)
scanf("%s",ch[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(ch[i][j]=='1') f[i][j]=f[i][j-1]+1;
/*for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++)
printf("%d ",f[i][j]);
puts("");
}*/
for(int i=n;i>=1;i--)
for(int j=1;j<=n;j++) {
minn=f[j][i];
cnt=1;
if(minn*(n-j+1)<=ans) continue;
ans=Max(ans,cnt*minn);
for(int k=j+1;k<=n;k++) {
minn=Min(minn,f[k][i]);
cnt++;
if(minn*(n-j+1)<=ans) break;
ans=Max(ans,cnt*minn);
}
}
printf("%d\n",ans);
return 0;
}
炸彈(Bomb.pas/c/cpp Time:1s Memory:256M)
【問題描述】
高老大又在鼓搗炸彈了,這不,啓動了一個了。英明英勇的老大又在跟他的部下們表演空手光速拆炸彈了。
炸彈上是一個圓盤,圓盤上順時針寫着N個數。其實這個炸彈就是要求從中選擇若干個連續的數(注意每個數最多隻能選一次)加起來,使得這些數字的和最大,然後輸入這個
最大的和,計時就會停止。現在你被老大要求上臺表演,時間是1s,任務就交給你了。
【輸入】
輸入文件名爲Bomb.in。
輸入第一行包含一個正整數N,表示數字的個數。
第二行包含N個整數,爲所給的數字。
【輸出】
輸出文件名爲Bomb.out。
輸出包含一個整數,爲最大的可以得到的和。
【輸入輸出樣例】
Bomb.in
8
2 -4 6 -1 -4 8 -1 3
Bomb.out
14
【數據範圍】
對於30%的數據
對於70%的數據
對於100%的數據
【題解】
這個題目可以很明顯的發現就是求最大連續子序列的題目
然後我們可以一般輕鬆的求出在非環上的最大連續子序列,
然後就是處理此時在環上的情況了。。。
我們將一個方案分成兩部分,一部分從 1 開始遞增,一部分從 n 開始遞減。
然後用dp就可以求出末端不超過 i 且從 1 或 n 出發的最大連續子序列。
然後就沒有然後了…
【代碼】
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
typedef int LL;
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
const int size = 200000+10;
LL n,ans;
LL a[size],f[size];
inline LL read() {
LL f=1,in=0;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())
if(ch=='-')
f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())
in=in*10+ch-'0';
return in*f;
}
inline LL erfen(LL l,LL r) {
if(l==r) return f[l];
LL mid=(l+r)>>1;
return Min(erfen(l,mid),erfen(mid+1,r));
}
int main() {
freopen("bomb.in","r",stdin);
freopen("bomb.out","w",stdout);
n=read();
for(LL i=1;i<=n;i++)
a[i]=a[i+n]=read();
LL m=n<<1;
for(LL i=1;i<=m;i++)
f[i]=f[i-1]+a[i];
LL minn=0;
for(LL i=n;i<=m;i++) {
if(f[i-n-1]==minn) minn=erfen(i-n,i);
else minn=Min(minn,f[i]);
ans=Max(ans,f[i]-minn);
}
printf("%d\n",ans);
return 0;
}
戰爭(War.pas/c/cpp Time:1s Memory:256M)
【問題描述】
高老大要打團戰了。他要召集N(N是奇數)個人去組織一場戰爭。現在高老大的手下有T個人,每個人都有一個戰鬥力值和影響力值。當這N個人的影響力值之和超過M的時候,必然會引起巨大的社會動盪。爲了愛與和平,老大明智地決定,不引起巨大的社會動盪。同時,英明的老大發現,一個團隊整體能力等於這N個人的戰鬥力的中位數,中位數越高則戰鬥力越強。現在老大想知道,這N個人的團隊整體能力最大爲多少。
【輸入】
輸入文件名爲War.in。
輸入第一行爲三個正整數N,T,M,意義如上述。
後接T行,每行兩個正整數Wi和Vi,代表每個人的戰鬥力值和影響力值。
【輸出】
輸出文件名爲War.out。
輸出一行一個整數,代表這N個人的團隊最大的整體能力。無解輸出-1。
【輸入輸出樣例】
War.in
3 5 70
30 25
50 21
20 20
5 18
35 30
War.out
35
【樣例解釋】
選第2、4、5個人,影響力21+18+30=69<=70,同時該團隊的整體能力爲最高的35。
【數據範圍】
對於30%的數據,保證
對於100%的數據,保證
【題解】
我當時一看這個題目,然後就開始準備打暴力,不怎麼想去想,然後打完暴力30分,再然後就…沒有然後了…
考後據說就是把每個人按照戰鬥力值進行排序,那麼枚舉中位數,對於第 i 個人,我們只需要求出
若它們之和再加上當前人的影響力值小於等於 m,就可以更新最大值。
在這之後就得要求區間前K大的數的和了。
只要建一個大根堆,每次比較當前數字與堆頂元素的大小關係,若比堆頂元素大,則不管;若比堆頂元素小,則取出堆頂元素,放入當前數字,然後更新和。
時間複雜度
【代碼】
先紀念我的30分暴力代碼
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxx = 200+10;
int n,t,m,ans=0;
bool yes;
int a[maxx],b[maxx],num[maxx];
struct people {
int c,w;
}ren[maxx];
bool cmp(const people &x,const people &y) {
return x.c<y.c;
}
void dfs(int k,int sum) {
int l=t-(n-k);
for(int i=a[k-1]+1;i<=l;i++)
if(sum+ren[i].w<=m) {
a[k]=i;
b[k]=ren[i].c;
if(k==n) {
yes=true;
if(k&1)
ans=max(ans,b[(k+1)/2]*2);
else
ans=max(ans,b[k/2]+b[k/2+1]);
}
else
dfs(k+1,sum+ren[i].w);
a[k]=0;b[k]=0;
}
}
int main() {
freopen("war.in","r",stdin);
freopen("war.out","w",stdout);
scanf("%d%d%d",&n,&t,&m);
if(t>25)
return 0;
for(int i=1;i<=t;i++)
scanf("%d%d",&ren[i].c,&ren[i].w);
sort(ren+1,ren+1+t,cmp);
if(t<=25)
dfs(1,0);
if(!yes)
puts("-1");
else {
if(ans&1)
printf("%.1lf\n",(double)ans/2.0);
else
printf("%d\n",ans/2);
}
return 0;
}
然後這是AC代碼
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
inline int read() {
int in=0,f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())
if(ch=='-')
f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())
in=in*10+ch-'0';
return in*f;
}
const int size = 100000+10;
struct Node {
int w,c,num;
bool operator > (const Node &A) const {
return A.c<c;
}
bool operator < (const Node &A) const {
return A.c>c;
}
}node[size];
inline bool cmp(const Node &a,const Node &b) {
return a.w<b.w;
}
int n,t;
LL m;
bool use[size];
priority_queue<Node ,vector<Node>,greater<Node> > q1;
priority_queue<Node ,vector<Node>,greater<Node> > q2;
priority_queue<Node ,vector<Node>,less<Node> > q3;
int main() {
freopen("war.in","r",stdin);
freopen("war.out","w",stdout);
n=read();t=read();m=read();
for(int i=1;i<=t;i++)
node[i].w=read(),node[i].c=read();
sort(node+1,node+t+1,cmp);
int k=n>>1;
LL sum1=0,sum2=0;
Node Top;
for(int i=1;i<=t;i++)
node[i].num=i;
for(int i=t-k-1;i>=1;i--)
q1.push(node[i]);
for(int i=t;i>t-k;i--)
q2.push(node[i]);
for(int i=1;i<=k;i++) {
Top=q1.top();q1.pop();
sum1+=Top.c;
use[Top.num]=true;
}
for(int i=1;i<=k;i++) {
Top=q2.top();
q2.pop();
sum2+=Top.c;
q3.push(Top);
}
for(int i=t-k;i>k;i--) {
if(use[i]) {
sum1-=node[i].c;
Top=q1.top();
while(use[Top.num]) {
q1.pop();
Top=q1.top();
}
sum1+=Top.c;
use[Top.num]=true;
q1.pop();
}
else use[i]=true;
if(sum1+sum2+node[i].c<=m) {
printf("%d\n",node[i].w);
return 0;
}
Top=q3.top();q3.pop();
sum2-=Top.c;q2.push(Top);
q2.push(node[i]);
Top=q2.top();q2.pop();
sum2+=Top.c;q3.push(Top);
}
puts("-1");
return 0;
}
總結
還得繼續想,dp水平才上的去啊,暴力少打點,多想些吧
最後%%%Yzy大神%%% 即將AK