总的来说,我感觉这次的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分吧)。

#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;
} 
View Code

 

Day1 T3飞扬的小鸟:

算法一:没什么算法,瞎基本搞搞就出来了(那百分之30的数据我也没办法啊。。。没管子能有什么算法。。。)。

算法二:尝试一下bfs,枚举到每个点的最小距离,然后就搞出来了(就是暴力)(40-50分)。

算法三:直接动态规划(然而我并不太会写。。公式没推出来)。。(据说可以拿到70分)。

算法四(正解):点击屏幕的是完全背包,下降的是01背包。然后就出来了(100分)。

#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;

}
View Code

 

posted on 2017-10-23 18:12  杯具-  阅读(122)  评论(0编辑  收藏  举报