Description (Special Judge)
We are given a sequence of Npositive integers a = [a1, a2, ..., aN] on which we can perform contractionoperations.
One contraction operation consists of replacing adjacent elements ai and ai+1by their difference ai-ai+1. For a sequence of N integers, we canperform exactly N-1 different contraction operations, each of which results ina new (N-1) element sequence.
Precisely, let con(a,i) denote the (N-1) element sequence obtained from [a1,a2, ..., aN] by replacing the elements ai and ai+1 by a singleinteger ai-ai+1 :
con(a,i) = [a1, ..., ai-1, ai-ai+1, ai+2, ..., aN]
Applying N-1 contractions to any given sequence of N integers obviously yieldsa single integer.
For example, applying contractions 2, 3, 2 and 1 in that order to the sequence[12,10,4,3,5] yields 4, since :
con([12,10,4,3,5],2) = [12,6,3,5]
con([12,6,3,5] ,3) = [12,6,-2]
con([12,6,-2] ,2) = [12,8]
con([12,8] ,1) = [4]
Given a sequence a1, a2, ..., aN and a target number T, the problem is to finda sequence of N-1 contractions that applied to the original sequence yields T.
Input
The first line of the inputcontains two integers separated by blank character : the integer N, 1 <= N<= 100, the number of integers in the original sequence, and the targetinteger T, -10000 <= T <= 10000.
The following N lines contain the starting sequence : for each i, 1 <= i<= N, the (i+1)st line of the input file contains integer ai, 1<= ai <= 100.
Output
Output should contain N-1lines, describing a sequence of contractions that transforms the originalsequence into a single element sequence containing only number T. The ith lineof the output file should contain a single integer denoting the ithcontraction to be applied.
You can assume that at least one such sequence of contractions will exist for agiven input.
Sample Input
5 4
12
10
4
3
5
Sample Output
2
3
2
1
题目简介:给N个数,例12,10,4,3,5。然后每次给你处理数在数列中的位置数,然后就用该数减去后面一个数,一直这样,直到得到T。[12,10,4,3,5],2表示处理第二个数,即10,用10减去4,得到[12,6,3,5],然后继续。[12,6,3,5] ,3,表示处理第三个数,即3,用3减去5,得到-2。继续。直到得到4。
方法:动态规划。可以看作是一串数之中添加+、-。除了第一个数和第二个数之间必须是减号连接,其他之间可加可减。之后就先处理加号。用f[i][j]记录下处理完前i个数得到j,f[i][j]存由f[i-1][]是加还是减得到f[i][j]的。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int f[110][20010], num[110], p[110];//f[i][j],表示处理了前i个数得到结果j。f[i][j]中保存的是由加还是减得到的。
int main()
{
int N, T;
scanf("%d%d",&N,&T);
for(int i = 1;i<=N;i++)
{
scanf("%d",&num[i]);
}
memset(f,-1,sizeof(f));
//加为1,减为0.显然第一个数和第二个数之间必须为减
f[1][num[1]+10000] = 1;
f[2][num[1] - num[2]+10000] = 0;
for(int i = 3;i<=N;i++)
{
for(int j = 0;j<=20000;j++)
{
if(f[i - 1][j]!=-1)
{
f[i][j + num[i]] = 1;
f[i][j - num[i]] = 0;
}
}
}
for(int i = N, j = T + 10000;i>=1;i--)
{
if(f[i][j]==1)
{
p[i] = 1;
j -= num[i];
}
else if(f[i][j]==0)
{
p[i] = 0;
j += num[i];
}
}
int count = 0;
//先处理加号,加号可以看作是 -(b-c)
for(int i = 2;i<=N;i++)
{
if(p[i]==1)
{
printf("%d\n",i - 1 - count);//看作是num[i]和num[i+1]被num[i]-num[i+1]取代了。
count++;
}
}
for(int i = 2;i<=N;i++)
{
if(p[i]==0)
{
printf("1\n");//开始没想通怎么输出。后来发现,处理完加号之后,减号的处理顺序无关紧要了,可以每次都是处理第一个数。
}
}
system("pause");
return 0;
}