总的来说,我感觉这次的noip还是比较水的。
Day1 T1石头剪刀布生活大爆炸版:
因为n<=200,所以数据还是比较水的,所以怎么搞应该都可以搞出来吧??
算法一:大概可以搞上十几个或者二十多个if,就好了。(没错我就是这样写的)
算法二:可以把蜥蜴人和斯波克换一下位置,惊奇的发现可以直接大减小出结果。
第一题就不贴代码了吧。。。
Day1 T2联合权值:
算法一:floyd求出距离,然后枚举距离为二的点,然后瞎搞。。。。(大概可以拿30分)时间复杂度O(n^3)。
算法二:枚举每个点,然后bfs每个与当前点距离为二的点。(70分左右,被一些神奇的图卡掉,比如菊花)时间复杂度为O(n^2)。
算法三:枚举每个点,然后它周围的两个不同的点距离就是二,搞上一遍就好了。
对于找最大值,要做的就是把点对的起点排序,使得起点相同的点对靠在一起。然后起点相同的点对以终点的价值排序,最后面两个价值的乘积更新答案。
这里大概有个神奇的优化:比如当前枚举的点有三个点与它相连。
S=w1*w2+w1*w3+w2*w3 =>S=w1*w2+(w1+w2)*w3.(这样枚举起来会方便许多,时间上也有一定的优化)。(100分吧)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <algorithm> #define maxn 200000 #define sqr(a) (a*a) #define smax(a,b) a=max(a,b) using namespace std; struct road_inf{int x,y;}a[maxn*2+1]; int w[maxn],n,sum=0,ans=0,tmp1=0,tmp2=0; bool comp(road_inf a,road_inf b){ return (a.x!=b.x)?(a.x<b.x):(a.y<b.y); } int main() { cin>>n; for (int i=1;i<n;i++){ cin>>a[i].x>>a[i].y; a[i+n-1].x=a[i].y; a[i+n-1].y=a[i].x; } for (int i=1;i<=n;i++)cin>>w[i]; n=(n-1)*2; for (int i=1;i<=n;i++)a[i].y=w[a[i].y]; sort(a+1,a+n+1,comp); for (int i=1;i<=n+1;i++){ if (a[i].x!=a[i-1].x){ int addsum=(sqr(tmp1)-tmp2)%10007; sum=(sum+addsum)%10007; if (a[i-1].x==a[i-2].x)smax(ans,a[i-1].y*a[i-2].y); tmp1=tmp2=0; } tmp1=(tmp1+a[i].y)%10007; tmp2=(tmp2+sqr(a[i].y))%10007; } cout<<ans<<" "<<sum%10007<<endl; }
Day1 T3飞扬的小鸟:
算法一:没什么算法,瞎基本搞搞就出来了(那百分之30的数据我也没办法啊。。。没管子能有什么算法。。。)。
算法二:尝试一下bfs,枚举到每个点的最小距离,然后就搞出来了(就是暴力)(40-50分)。
算法三:直接动态规划(然而我并不太会写。。公式没推出来)。。(据说可以拿到70分)。
算法四(正解):点击屏幕的是完全背包,下降的是01背包。然后就出来了(100分)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> int n,m,k,x[10001],y[10001],xx[10001],yy[10001],f[2][1001]; int MAX=0xfffffff,ljj=0; bool b[10001],bo; int min(int a,int b){return a>b?b:a;} int main() { scanf("%d%d%d",&n,&m,&k); for (int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]); for (int i=1;i<=n;i++) xx[i]=1,yy[i]=m; int P,L,H; for (int i=1;i<=k;i++) { scanf("%d%d%d",&P,&L,&H); xx[P]=L+1; yy[P]=H-1; b[P]=1; } int pjy=1,eden=0; for (int i=1;i<=n;i++) { bo=0; pjy^=1; eden^=1; for (int j=1;j<=m;j++) f[pjy][j]=MAX; for (int j=x[i-1]+1;j<m;j++) f[pjy][j]=min(f[pjy][j],min(f[eden][j-x[i-1]]+1,f[pjy][j-x[i-1]]+1)); for (int j=m-x[i-1];j<=m;j++) f[pjy][m]=min(f[pjy][m],min(f[eden][j]+1,f[pjy][j]+1)); for (int j=xx[i];j<=yy[i];j++) { if (j+y[i-1]<=m) f[pjy][j]=min(f[pjy][j],f[eden][j+y[i-1]]); if (f[pjy][j]<MAX) bo=1; } for (int j=0;j<xx[i];j++) f[pjy][j]=MAX; for (int j=yy[i]+1;j<=m;j++) f[pjy][j]=MAX; if (!bo){printf("0\n%d",ljj);return 0;} if (b[i]) ljj++; } /*for (int j=m;j>=1;j--) { for (int i=1;i<=n;i++) printf("%d ",f[i][j]); printf("\n"); }*/ for (int i=xx[n];i<=yy[n];i++) MAX=min(MAX,f[pjy][i]); printf("1\n%d",MAX); return 0; }