校内hu测(10.6T2,T3)(乱搞+贪心+模拟)

来源:互联网 发布:在淘宝上怎么开充值店 编辑:程序博客网 时间:2024/06/15 19:40

@liu_runda

T2.便(then)

【题目描述】
给出一个R*C的棋盘.共有R行C列,R*C个格子.现要在每个格子都填一个非负整数.使得任意一个2*2的正方形区域都满足这样的性质:左上角的数字+右下角的数字=左下角的数字+右上角的数字.有些格子已经确定,你不能更改其中的数字.其他格子的数字由你决定.
这是一个符合要求的3*3的棋盘:
1 2 3
2 3 4
4 5 6

不难验证每个2*2的区域都是符合要求的.
Orbitingflea想要知道一个可行的填充棋盘的方案.但是这个方案可能很大.所以你只需对给定的棋盘判定是否存在至少一种可行的填充棋盘的方案.

【输入格式】
第一行输入一个T,表示数据组数。接下来T组数据。
每组数据的第1行2个整数R,C表示棋盘的大小.
第2行1个整数n表示已经被填好数字的格子的数目.
接下来n行每行3个整数ri,ci,ai,表示第ri行ci列的格子被填上了数字ai.

【输出格式】
T行.第i行是第i组数据的答案.有合法方案时输出一行Yes,没有时输出一行No.

【样例输入】
6

2 2
3
1 1 0
1 2 10
2 1 20

2 3
5
1 1 0
1 2 10
1 3 20
2 1 30
2 3 40

2 2
3
1 1 20
1 2 10
2 1 0

3 3
4
1 1 0
1 3 10
3 1 10
3 3 20

2 2
4
1 1 0
1 2 10
2 1 30
2 2 20

1 1
1
1 1 -1
【样例输出】
Yes
No
No
Yes
No
No

【数据范围】
第1个测试点,R=1
第2,3个测试点,R*C<=12,如果有解,保证存在一个解使得所有数字大小不超过2
第4,5个测试点,R=2
第6,7个测试点,R=3
第8个测试点,1<=R,C<=20
第9个测试点,1<=R,C<=100
对于全部测试点,1<=T<=6,1<=R,C,n<=100000,1<=ri<=R,1<=ci<=C,同一个格子不会多次被填上数字.ai是整数且绝对值不超过10^9.

分析:
Atcoder 2016 qual A D题

考场上猜规律:
观察发现:
相邻两行如果有一列都有数字
那么这两个数字的差值就是这两列所有数字都应该遵循的差值
同时注意计算出差值后
时刻判断矩阵中不会出现负数
(只要一行中的最小值加减差值不会出现负数就行)

int pd(){    memset(h,-1,sizeof(h));    int i=1,hh=po[1].x,d;    int now=0;    minn[now]=INF;    while (po[i].x==hh)     {        if (po[i].a<0) return 0;        h[po[i].y][now]=po[i].a;        minn[now]=min(minn[now],po[i].a);        i++;    }    while(i<=nn)    {        hh=po[i].x;        d=-1; now^=1;        for (int j=1;j<=m;j++) h[j][now]=-1;        minn[now]=INF;   //这一行中的最小值         while (po[i].x==hh)        {            if (po[i].a<0) return 0;            if (h[po[i].y][now^1]!=-1)  //上一行这里有数             {                if (d==-1)   //第一次相等                 {                    d=po[i].a-h[po[i].y][now^1];                    h[po[i].y][now]=po[i].a;                    minn[now]=min(minn[now],po[i].a);                     if (minn[now]-d<0||minn[now^1]+d<0) return 0;   //非负整数                }                else                {                    if (po[i].a-h[po[i].y][now^1]!=d) return 0;                    minn[now]=min(minn[now],po[i].a);                     h[po[i].y][now]=po[i].a;                }            }            else            {                h[po[i].y][now]=po[i].a;                minn[now]=min(minn[now],po[i].a);                if (d!=INF)                    if (minn[now]-d<0) return 0;            }            i++;        }    }     return 1;}

舒老师给出一种更科学的做法:
观察发现,所有的正方形
左上角+右下角=右上角+左下角
暴力判断即可

T3.做(do)

【题目描述】
你是一个位于无限大二维平面上没有近战能力的膜法师,无限大二维平面上还有一个只有近战能力的香港记者.
你们都在整点上.每个回合你先行动,香港记者后行动.
香港记者的目标是使你被续.你的目标是让香港记者被续.
香港记者有一个属性是森破值,当他的森破值小于等于零他将立刻被续.
因为香港记者的近战能力比你高到不知道哪里去了,如果任意时刻你和香港记者位于同一个整点,你将立即被续.
人物(膜法师或香港记者)被续之后就被得罪了一下,从二维平面上消失了.
香港记者只有一种行动模式:移动,香港记者因为跑得比谁都快,一个回合可以移动两次.每次可以在上下左右四个方向中选一个移动一步.当然也可以选择不动.也就是说,一个回合内香港记者可以到达曼哈顿距离小于等于2的任意位置.
你在回合中可以在3种操作中选一种:
1.移动,你一个回合只能移动1次. 也就是说,一个回合内你可以到达曼哈顿距离小于等于1的任意位置.
2.膜.大呼”蛤蛤蛤”,消耗a点膜法值.对香港记者造成伤害.香港记者的森破值会减小,减小的量等于你与香港记者之间的欧几里得距离的平方.即,若你在(x1,y1),香港记者在(x2,y2),香港记者的森破值将减少(x1-x2)^2+(y1-y2)^2.膜法值不足a则不能膜.
3.念诗.大呼”苟利国家生死以,竹外桃花三两枝”,回复b点膜法值.
一开始你有c点膜法值.之后你的膜法值可以超过c.
香港记者有一个好,脑子转得比谁都快,会选择最优策略.
如果你会被续,输出”SIMPLE”,如果香港记者会被续,输出“NAIVE”
多组数据.

【输入格式】
第一行一个正整数T表示数据组数
第二行两个空格隔开的整数a,b,含义见【题目描述】.
接下来T行,每行描述一组数据.这T行每行为6个空格隔开的整数
X1,Y1,X2,Y2,c,d.
表示你的初始坐标是(X1,Y1),香港记者的初始坐标是(X2,Y2).你一开始有c点膜法值,香港记者一开始有d点森破值.

【输出格式】
T行,一行一个字符串”SIMPLE”或者“NAIVE”.

【样例输入】
2
2 1
0 0 10 10 0 10000
0 0 10 10 0 10

【样例输出】
SIMPLE
NAIVE

【数据范围】
第1个测试点,1<=|X1-X2|+|Y1-Y2|<=6
第2个测试点,1<=|X1-X2|+|Y1-Y2|<=7
第3个测试点, 1<=|X1-X2|+|Y1-Y2|<=8
第4,5个测试点,a=0
第6,7个测试点,b=0
100%的数据,T=10^5.1<=X1,X2,Y1,Y2<=10^9
|X1-X2|<=300,|Y1-Y2|<=300
0<=a,b,c<=100

分析:
对于”我“来说,移动是没有用的
既不能蓄力,还会拉近距离,
所以这道题就是一个贪心+模拟
能蓄力就蓄力,
能膜就膜

tip

注意判断b=0的情况
如果能力值一直达不到的话,直接输出”SIMPLE“

在我们进行攻击之后的同一秒
香港记者也是会移动的

时刻注意判断香港记者是否和我们在同一个点了

//这里写代码片#include<cstdio>#include<cstring>#include<iostream>using namespace std;int a,b,c,d,x,y,xx,yy;int xa,ya;int sqr(int x) {return x*x;}int abs(int x) {if (x>0) return x;else return -x;}int main(){    freopen("do.in","r",stdin);    freopen("do.out","w",stdout);    int T;    scanf("%d",&T);    scanf("%d%d",&a,&b);    while (T--)    {        scanf("%d%d%d%d%d%d",&x,&y,&xx,&yy,&c,&d);        if (c<a&&b==0)        {            printf("SIMPLE\n");            continue;        }        xa=abs(xx-x);        ya=abs(yy-y);        int ans=0,dis;        bool pp=0;        while (xa>0||ya>0)        {            while (c<a&&(xa||ya))    //xa||ya            {                if (xa>ya&&xa>1) xa-=2;                else if (xa<ya&&ya>1) ya-=2;                else                 {                    if (xa>0) xa--;                    if (ya>0) ya--;                }                c+=b;            }            if (xa>0||ya>0) dis=sqr(xa)+sqr(ya);   //xa||ya            else dis=0;            ans+=dis;            c-=a;            if (xa>ya&&xa>1) xa-=2;            else if (xa<ya&&ya>1) ya-=2;            else             {                if (xa>0) xa--;                if (ya>0) ya--;            }            if (ans>=d) {                pp=1;                break;            }        }        if (pp) printf("NAIVE\n");        else printf("SIMPLE\n");    }    return 0;   }