您的位置:首页 > 其它

ZOJ Candies 长沙

2013-09-23 18:49 579 查看
题意:有n个小孩,他们手上有很多糖果,善良的小孩会告诉你他有多少糖果,相反,则不会告诉你,但是会告诉你他和他的邻居的糖果和,求出每个人最多拥有多少糖果。

题目链接:http://acm.zju.edu.cn/changsha/showProblem.do?problemId=31

思路:n个人的号码是有1-n,,由于每次给出的是三个数的和(最边上的可以认为是0),很容易确定3,6,9,12,,,,,,的糖果数量,

另外,在以下几种情况下,这个序列的值都可以确定:

            1.如果在剩余的那些号码中有已知的量,那么这个序列的值都可以确定;

            2.如果n%3==0 || n%3==1 这个序列分别从头到尾和从尾到开始在求一次就可以确定;

那么接下来的情况(n%3==2)就是不确定这个序列,(除了Mode3==0的位置确定外)

对于以下序列 a,b,c,d,e,f,g,h,,,,,,

sum1=a+b;           sum2=a+b+c;          sum3=b+c+d;       sum4=c+d+e;

sum5=d+e+f;        sum6=e+f+g;           sum7=f+g+h;       sum8=g+h;

由于确定c,f,的值,那么上述不等式可以转换为:

x1 = a + b;   x2 = b + d;  x3 = d + e;  x4 = e + g; x5 = g + h;  (x1,x2,x3,x4,x5都可以求出来)

那么上述的这些式子就全部可以转换为和a有关系的函数式: b = x1 - a ; d = x2 - b = x2 - x1 + a; ,,,,,,,,,,,,

每个变量本身是大于等于0,所以我们可以确定a的最大值和最小值,

从而每个变量的最大值也就确定~~~~~~~

比赛的时候没写出来,代码太渣,,,还是纪念下来,

 

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 100010
#define inf 0x3f3f3f3f

int s[maxn]; //记录两个未知数的和
int num[maxn];
int num2[maxn];
int sum[maxn];

int main()
{
int n,m,query,pos;
while(~scanf("%d",&n)){
memset(s,0,sizeof(s));
memset(num,0,sizeof(num));
memset(num2,0,sizeof(num2));
memset(sum,0,sizeof(sum));
bool flag=false;
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
if(i%3){if(num[i]!=-1) {flag=true;pos=i;}} //记录是否有除了3,6,9..之外的值给出。。。
num2[i]=num[i];
}

for(int i=1;i<=n;i++)
scanf("%d",&sum[i]);

for(int i=1;i<=n;i++) //确定位置3.6.9.12....的值
if(i%3==0) num[i] = sum[i-1] - sum[i-2] + num[i-3];

if(n%3==0){        //确定n%3==0序列
for(int i=n;i>=1;i--)   //确定mode3==1的位置的数
if(i%3==1)
num[i] = sum[i+1] - sum[i+2] + num[i+3];

for(int i=1;i<=n;i++)
if(i%3==2) //确定mode3==2的位置的数
num[i] = sum[i] -num[i-1] -num[i+1];

scanf("%d",&m);
while(m--){
scanf("%d",&query); query++;
printf("%d\n",num[query]);
}
}
else if(n%3==1){   //确定n%3==1序列
num
= sum
- num[n-1];
for(int i=n-2;i>=1;i--)
num[i] = sum[i+1] - num[i+1] -num[i+2];

scanf("%d",&m);
while(m--){
scanf("%d",&query); query++;
printf("%d\n",num[query]);
}
}
else{
if(flag==true){ //有值给出的情况
if(pos%3==2){
num[pos-1] = sum[pos-1] -num[pos-2] -num[pos];
pos=pos-1;
}
for(int i=pos-2;i>=1;i--)
num[i]=sum[i+1]-num[i+1] -num[i+2];
for(int i=pos+1;i<=n;i++)
num[i]=sum[i-1]-num[i-1]-num[i-2];

scanf("%d",&m);
while(m--){
scanf("%d",&query);query++;
printf("%d\n",num[query]);
}
}
else{
int t=1; //记录两个变量的和
for(int i=1;i<=(n-2);i++){
if(i%3==2){
s[t++] = sum[i] - num[i+1];
s[t++] = sum[i+1] - num[i+1];
}
}
s[t] = sum
;

int mi=0,ma=inf,temp=0,cnt=1; //记录a 的可变范围
for(int i=2;i<=n;i++){
if(i%3){
num[i] = s[cnt++] - temp;
if(i%3==1) mi=max(mi,-num[i]);
else if(i%3==2) ma=min(ma,num[i]);
temp=num[i];
}
}
num[1] = 0;
scanf("%d",&m);
while(m--){
scanf("%d",&query);
query++;
if(num2[query]!=-1) printf("%d\n",num2[query]);
else{
if(query%3==0) printf("%d\n",num[query]);
else if(query%3==1) printf("%d\n",num[query]+ma);
else printf("%d\n",num[query]-mi);
}
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  zoj 乱搞