201809-4 | |
试题名称: | 再卖菜 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 在一条街上有n个卖菜的商店,按1至n的顺序排成一排,这些商店都卖一种蔬菜。 输入格式 输入的第一行包含一个整数n,表示商店的数量。 输出格式 输出一行,包含n个正整数,依次表示每个商店第一天的菜价。 样例输入 8 样例输出 2 2 2 1 6 5 16 10 数据规模和约定 对于30%的评测用例,2<=n<=5,第二天每个商店的菜价为不超过10的正整数; |
思路:
剪枝1:
vis[][][]数组记录在到达第s个位置时(此时b[s],b[s-1]均已知),根据关系推知b[s+1] = 3*a[s]-b[s]-b[s-1]+i(因为题目给的是整数除法,其中 0..2),这样,当到达当前状态时(状态 : (s,b[s-1],b[s])),如果发现已经访问过了,说明这种状态不可能满足条件,否则程序已经找到满意的结果,可以直接输出了,这样可以直接剪枝掉之后的所有步骤,效率大大增加。
剪枝2:
用flag标记 是否已经找到解,如果找到,之后的所有未完成的搜索,直接返回。
注意:第一个位置,与最后的位置单独处理一下。
code:
#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<cstring>
#include<set>
#include<cmath>
#include<queue>
#include<algorithm>
#define rep(i,j,k) for(int i=j;i<k;++i)
#define mst(a,b) memset((a),(b),sizeof(a))
#include<cstring>
using namespace std;
typedef long long LL;
typedef vector<int,int> pii;
const int MAXN = 305;
int n;
int a[MAXN];
int b[MAXN];
bool vis[MAXN][MAXN][MAXN];
bool flag;
void dfs(int s, int p1, int p2){
if(vis[s][p1][p2] || flag) return;
vis[s][p1][p2] = true;
if(s == n-1){
rep(i,0,3){//单独处理最后一个
if((b[n] = (3*a[s]-p1-p2+i)) > 0 && (b[n-1] + b[n])/2 == a[n]){
flag = true;
rep(i,1,n+1){
printf("%d ",b[i]);
}
break;
}
}
return;
}
rep(i,0,3){
b[s+1] = 3*a[s]- p1 - p2 + i;//递推下一个位置的b[s+1]
if(b[s+1] > 0){ // 可能有解
dfs(s+1,b[s],b[s+1]);
}
}
}
int main()
{
scanf("%d",&n);
rep(i,1,n+1) scanf("%d",&a[i]);
rep(i,1,2*a[1]+1){//最大只能是 2*a[1]
b[1] = i; b[2] = a[1]*2-b[1];
dfs(2,b[1],b[2]);
b[1] = i; b[2] = a[1]*2-b[1]+1;
dfs(2,b[1],b[2]);
}
return 0;
}