用队列模拟题意便可node
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int n,m; int head=0,tail=0; int s[1100]; long long ans=0; bool book[1100]; int main(){ cin>>m>>n;memset(book,0,sizeof(book)); for(int i=1;i<=n;++i){ int a;cin>>a; if(book[a]==0){ s[++tail]=a;book[a]=1;//入队 if(head+m<=tail)//出队 book[s[head++]]=0; ++ans; } } cout<<ans<<endl; return 0; }
根据题意能够尝试爆搜
30ptsios
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int n,m; long long ans=0; int a[390]; int b[6]; void dfs(int now,long long fs){ if(now==n) {ans=max(ans,fs);return ;} for(int i=1;i<=4;++i){ if(b[i]){ b[i]--; dfs(now+i,fs+a[now+i]); b[i]++; } } } int main(){ cin>>n>>m; for(int i=1;i<=n;++i) cin>>a[i]; for(int i=1;i<=m;++i) { int u;cin>>u;++b[u];} dfs(1,a[1]); cout<<ans<<endl; return 0; }
正解应该用动态规划
定义\(f[i][j][k][l]\)数组,到某个位置用了i张1牌,j张2牌,k张3牌,l张4牌
初始状态:\(f[0][0][0][0]==val[1]\)(val数组记录分数,val[1]为第一张格子的分数)
末状态:\(f[m_1][m_2][m_3][m_4](m_x为第x张牌数量)\)
状态转移方程:
\(t=1*a+b*2+3*c+4*d(a,b,c,d分别为用过的1,2,3,4牌,t为下一步乌龟棋会到达的位置)\)
\(f[i][j][k][l]=min(f[i-1][j][k][l]+val[t],f[i][j][k][l])\)
\(f[i][j][k][l]=min(f[i][j-1][k][l]+val[t],f[i][j][k][l])\)
\(f[i][j][k][l]=min(f[i][j][k-1][l]+val[t],f[i][j][k][l])\)
\(f[i][j][k][l]=min(f[i][j][k][l-1]+val[t],f[i][j][k][l])\)数组
#include<cstdio> #include<iostream> using namespace std; int n,m;const int maxn=360; int val[maxn]; int f[111][111][111][111]; int a=0,b=0,c=0,d=0; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&val[i]); for(int i=1,x;i<=m;++i){ scanf("%d",&x); if(x==1) ++a;if(x==2) ++b;if(x==3) ++c;if(x==4) ++d; }f[0][0][0][0]=val[1]; for(int i=0;i<=a;++i) for(int j=0;j<=b;++j) for(int k=0;k<=c;++k) for(int l=0;l<=d;++l){ int t=1*i+j*2+k*3+l*4+1;//乌龟棋下一步能走到那个位置 if(i!=0) f[i][j][k][l]=max(f[i-1][j][k][l]+val[t],f[i][j][k][l]); if(j!=0) f[i][j][k][l]=max(f[i][j-1][k][l]+val[t],f[i][j][k][l]); if(k!=0) f[i][j][k][l]=max(f[i][j][k-1][l]+val[t],f[i][j][k][l]); if(l!=0) f[i][j][k][l]=max(f[i][j][k][l-1]+val[t],f[i][j][k][l]); } printf("%d",f[a][b][c][d]);return 0; }
(文字量较大建议细读题目)spa
影响力从大到小排成一个列表
市长只看第一件事
因此能够很容易想到,尽量把最大值减少
那么所以,(能够贪心)尽可能依次拆分两个怒气值最大的两人到两个监狱,遇到两人没法拆开那么就是正确答案(没法拆开说明他们与其余人有更大的c翻译
按影响力c排个序,用并查集记录同一个监狱里的人,又用一个数组记录这个监狱里的对立的人code
#include<cstdio> #include<algorithm> using namespace std; int n,m;const int maxn=2e4+10; int f[maxn],d[maxn];//f为并查集,d记录敌人 struct node{ int u,v,w; }e[maxn*10]; bool cmp(node a,node b){ return a.w>b.w; } int find(int x){ if(x!=f[x]) return f[x]=find(f[x]); return x; } bool check(int x,int y){ return find(x)==find(y)?1:0; } void unite(int x,int y){ f[find(x)]=find(y); } int main(){ scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)f[i]=i; for(int i=1;i<=m;++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); sort(e+1,e+1+m,cmp); for(int i=1;i<=m;++i){ int u=e[i].u,v=e[i].v; if(check(u,v)){ printf("%d",e[i].w); return 0; } else { if(!d[u]) d[u]=v; else unite(d[u],v); if(!d[v]) d[v]=u; else unite(d[v],u); } } printf("0");return 0; }
对因而否具备可行性
只须要dfs或bfs判断一下就ok队列
对于最少建造几个蓄水厂
也能够用爆搜搜出每一个点从上到下能覆盖几个线段,而后贪心线段覆盖便可
至于时间复杂度卡常就能够过去ci
记忆化搜索其实就是直接拿搜过的结果用
dp数组的是每一个点能到达的最左最右距离
因此要两个数组
l[x][y]=min(l[i][j])(点i,j为点x,y能到达的全部点)
l记录最左端
r记录最右端get
#include<cstdio> #include<algorithm> using namespace std; int n,m;const int maxn=505; bool vl[maxn][maxn]; struct node{ int l,r; }d[maxn][maxn]; int mp[maxn][maxn];int cnt=0; int nt[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; inline int minn(int x,int y){ return x<y?x:y; } inline int maxx(int x,int y){ return x>y?x:y; } inline int read(){ int x=0,f=1; char c=getchar(); while(c>'9' || c<'0'){ if(c=='-') f=-1; c=getchar(); } while(c>='0' && c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); }return x*f; } inline int dfs(int x,int y){ vl[x][y]=1;if(x==n) ++cnt; int nx,ny; for(int i=0;i<4;++i){ nx=x+nt[i][0],ny=y+nt[i][1]; if(nx<1 || ny<1 || nx>n || ny>m || mp[nx][ny]>=mp[x][y]) continue; if(!vl[nx][ny])dfs(nx,ny); d[x][y].l=minn(d[x][y].l,d[nx][ny].l); d[x][y].r=maxx(d[x][y].r,d[nx][ny].r); } } int main(){ n=read();m=read(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) mp[i][j]=read(),d[i][j].l=0x3f3f3f3f,d[i][j].r=0; for(int i=1;i<=m;++i) d[n][i].l=d[n][i].r=i;//dp边界 for(int i=1;i<=m;++i) if(!vl[1][i]) dfs(1,i); if(cnt!=m){ printf("0\n%d",m-cnt);return 0; //m-cnt为不能建造的水利设施 }int last=1;cnt=0; while (last<=m){ int maxr=0; for (int i=1;i<=m;i++) if (d[1][i].l<=last) maxr=max(maxr,d[1][i].r); cnt++; last=maxr+1; }puts("1");printf("%d",cnt);return 0; }
ZFY AK IOIstring