noip online 入门组
文具订购
枚举每种情况,比较找出最优的那种就可以了。
时间复杂度好像有点高,应该是擦着边过的。(我以为过不了,结果学校oj给过了)
#include<bits/stdc++.h> using namespace std; int ans,ans2=-1; int a,b,c; int cmp(int a,int b,int c) { if(a>=c&&b>=c) return c; if(b<=a&&b<=c) return b; else return a; } int main() { int n; scanf("%d",&n); if(n==0) { printf("0 0 0"); return 0; } else { for(int i=0;i<=n/7;i++) { for(int j=0;j<=n/4;j++) { int k=n-7*i-4*j; if(k%3==0&&k>=0) { k/=3; int s=cmp(i,j,k); if(ans<s) { ans=s; ans2=i+j+k; a=i;b=j;c=k; } else if(ans==s) { if(ans2<i+j+k) { ans2=i+j+k; a=i;b=j;c=k; } } } } } } if(ans2!=-1) printf("%d %d %d",a,b,c); else cout<<-1; return 0; }
跑步
一开始就很明显直接用背包就能做。
相当于的一个二维dp,状态转移方程:f[i][j]=f[i-1][j-1]+f[i-j][j]。
但是会超时,只能拿70分。
所以在这个二维的基础上利用乘法原理再优化。
分成两种情况:
小于根号n,此时可以把上面的二维dp化成一维:f[j]=f[j]+f[j-i]。
大于等于根号n时,状态转移方程为:f[i][j]=f[i][j-i],f[i-1][j-m]。
最后,两种情况相乘合并就可以了。
70分代码:
#include<bits/stdc++.h> using namespace std; int n,MOD,ans; int f[5005][5005]; int main() { scanf("%d%d",&n,&MOD); for(int i=1;i<=n;i++) f[i][1]=1; for(int i=2;i<=n;i++) { for(int j=2;j<=i;j++) { f[i][j]=(f[i-1][j-1]+f[i-j][j])%MOD; } } for(int i=1;i<=n;i++) ans+=f[n][i],ans%=MOD; printf("%d\n",ans); return 0; }
100分代码:
#include<bits/stdc++.h> long long d[100002],f[1002][100002]; int main() { int n,MOD; scanf("%d%d",&n,&MOD); int m=sqrt(n)+1; d[0]=f[0][0]=1; for(int i=1;i<m;i++) { for(int j=i;j<=n;j++) { d[j]=(d[j]+d[j-i])%MOD; } } for(int i=1;i<m;i++) { for(int j=i;j<=n;j++) { f[i][j]=f[i][j-i]; if(j>=m) f[i][j]=(f[i][j]+f[i-1][j-m])%MOD; } } long long ans=0; for(int i=0;i<=n;i++) { long long x=0; for(int j=0;j<m;j++) { x=(x+f[j][n-i])%MOD; } ans+=x*d[i]; ans%=MOD; } printf("%d",ans); return 0; }
魔法
因为有6个点都是k=0的特殊情况,此时就是一个纯的最短路算法。
用Floyd骗了30分。
#include<bits/stdc++.h> using namespace std; long long f[102][102]; int main() { int n,m,k; scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=100;i++) { for(int j=1;j<=100;j++) { f[i][j]=10000000000; } } for(int i=1;i<=m;i++) { int t,u,v; scanf("%d%d%d",&u,&v,&t); f[u][v]=t; } for(int k2=1;k2<=n;k2++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) f[i][j]=min(f[i][j],f[i][k2]+f[k2][j]); } } printf("%lld\n",f[1][n]); return 0; }
正解等我来填坑吧。