盲人oi,the best oi
T1:
DP+贪心
贪心地让以i为结尾的序列的最后一段最小,直接转移。
#include <bits/stdc++.h>
const int N=200005;
long long n,h[N],f[N],sum[N],las[N];
int main(){
freopen("tower.in","r",stdin);
freopen("tower.out","w",stdout);
std::cin>>n;
for(int i=1;i<=n;i++) std::cin>>h[i],sum[i]=sum[i-1]+h[i];
f[1]=1;las[1]=h[1];f[0]=0;
for(int i=2;i<=n;i++)
for(int j=i-1;~j;j--)
if(sum[i]-sum[j]>=las[j]) {f[i]=f[j]+1;las[i]=sum[i]-sum[j];break;}
std::cout<<n-f[n];
}
T2:
简单DP,分类讨论即可。
数组开小100倍海星,改了直接A。。。。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct CLASS{int k,c;}w[10005];
int t,s,n,g[10005],f[10005][105],a[105];
int main() {
freopen("wrk.in","r",stdin);
freopen("wrk.out","w",stdout);
memset(a,0x3f,sizeof a);
scanf("%d%d%d",&t,&s,&n);
for(int i=1,tt,e;i<=s;i++)
scanf("%d%d",&tt,&e),scanf("%d",&w[tt+e].c),w[tt+e].k=e;
for(int i=1,tt,r;i<=n;i++)
scanf("%d%d",&tt,&r),a[tt]=min(a[tt],r);
for(int i=1;i<=100;i++) a[i]=min(a[i],a[i-1]);
memset(f,0xcf,sizeof f);
f[0][1]=0;
for(int i=1;i<=t;i++) {
for(int j=1;j<=100;j++) f[i][j]=f[i-1][j];
for(int j=100;j&&a[j]<=i;j--) {
f[i][j]=max(f[i][j],f[i-a[j]][j]+1);
}
if(w[i].k)
for(int j=1;j<w[i].c;j++)f[i][w[i].c]=max(f[i-w[i].k][j],f[i][w[i].c]);
}
int ans=0;
for(int i=1;i<=100;i++) ans=max(ans,f[t][i]);
cout<<ans;
}
T3
题解参见Candy?
https://www.cnblogs.com/candy99/p/6003565.html
#include <bits/stdc++.h>
using namespace std;
const int N=2005,inf=0x3f3f3f3f;
int n,m,k,head[N],ecnt,du[N],dis[N],len,rt;
struct Edge {int to,nxt;} e[N*N<<1];
void add(int bg,int ed) {e[++ecnt].nxt=head[bg];e[ecnt].to=ed;head[bg]=ecnt;}
bool vis[N];
void dfs(int x) {vis[x]=1,len++;for(int i=head[x]; i; i=e[i].nxt) {int v=e[i].to;if(!vis[v]) dfs(v);}}
void bfs(int x) {
queue<int>q;q.push(x);
memset(dis,-1,sizeof dis);dis[x]=0;
while(!q.empty()) {
int u=q.front();q.pop();
for(int i=head[u]; i; i=e[i].nxt) {
int v=e[i].to;
if(dis[v]==-1) {dis[v]=dis[u]+1;q.push(v);}
}
}
}
bool ck(int dist) {
int ans=inf;
for(int x=1; x<=n; x++) {
bfs(x);
if(dis[rt]>dist) continue;
int cnt=0;
memset(vis,0,sizeof vis);
for(int i=1; i<=n; i++) if(dis[i]<=dist) vis[i]=1;
for(int i=1; i<=n; i++)
if(!vis[i]) {len=0;dfs(i);cnt+=(len-1)/(2*dist+1)+1;}
ans=min(ans,cnt+1);
}
return ans<=k;
}
int main() {
freopen("holes.in","r",stdin);
freopen("holes.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(int i=1,u,v; i<=m; i++) {scanf("%d%d",&u,&v);add(u,v);add(v,u);du[u]++,du[v]++;}
for(int i=1; i<=n; i++) if(du[i]>3) {rt=i;break;}
if(!rt) return !printf("%d
",(n+k-1)/(2*k));
int l=1,r=n,ans=inf;
while(l<=r) {
int mid=l+r>>1;
if(ck(mid)) r=mid-1,ans=min(ans,mid);
else l=mid+1;
}
cout<<ans;
}