[题解]某模拟题(USACO月赛部分题+noip2005部分题)
Posted 阿波罗2003
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解]某模拟题(USACO月赛部分题+noip2005部分题)相关的知识,希望对你有一定的参考价值。
题目描述
农场上有N(1 <= N <= 50,000)堆草,放在不同的地点上。FJ有一辆拖拉机,也在农场上。拖拉机和草堆都表示为二维平面上的整数坐标,坐标值在1..1000的范围内。拖拉机的初始位置与所有草堆不同。
FJ开拖拉机时,只能平行于坐标轴(即东、南、西、北四个方向),而且每次开动的一段必须是整数长度。
例如,他可以向北开2个单位长度,然后向东开3个单位长度。拖拉机不能开到草堆的位置。
请帮助FJ计算出最少要移动多少个草堆,他才能将拖拉机开回坐标原点。
拖拉机可以开到1..1000之外的地方去。
输入
第1行: 3个整数,即N 和拖拉机的初始位置 (x,y)
第2..1+N行: 每行2个整数,表示一堆草的位置 (x,y)
输出
第1行: FJ必须移动的最少的草堆的数量
样例输入
7 6 3 6 2 5 2 4 3 2 1 7 3 5 4 6 4
样例输出
1
1
提示
样例说明:拖拉机初始在(6,3),7堆草分别在 (6,2), (5,2), (4,3), (2,1), (7,3), (5,4), (6,4).
FJ必须移动一堆草
水题,不多说,spfa跑到边界就可以了,只不过由于我比较懒,所以还是让它跑到原点
Code
1 #include<iostream> 2 #include<fstream> 3 #include<sstream> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<ctime> 8 #include<cctype> 9 #include<cmath> 10 #include<algorithm> 11 #include<stack> 12 #include<queue> 13 #include<set> 14 #include<map> 15 #include<vector> 16 using namespace std; 17 typedef bool boolean; 18 #define smin(a, b) (a) = min((a), (b)) 19 #define smax(a, b) (a) = max((a), (b)) 20 template<typename T> 21 inline void readInteger(T& u){ 22 char x; 23 int aFlag = 1; 24 while(!isdigit((x = getchar())) && x != -1); 25 if(x == -1){ 26 x = getchar(); 27 aFlag = -1; 28 } 29 for(u = x - \'0\'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - \'0\'); 30 ungetc(x, stdin); 31 u *= aFlag; 32 } 33 34 typedef class Point{ 35 public: 36 int x; 37 int y; 38 Point(const int x = 0, const int y = 0):x(x), y(y){ } 39 }Point; 40 41 const int mover[2][4] = {{1, 0, -1, 0}, {0, 1, 0, -1}}; 42 43 int n; 44 int sx, sy; 45 int bx, by; 46 int f[1005][1005]; 47 boolean cd[1005][1005]; 48 boolean inque[1005][1005]; 49 boolean visited[1005][1005]; 50 51 boolean isExeeded(Point& p){ 52 if(p.x < 0 || p.y < 0) return true; 53 if(p.x > bx || p.y > by) return true; 54 return false; 55 } 56 57 queue<Point> que; 58 inline int spfa(){ 59 que.push(Point(sx, sy)); 60 visited[sx][sy] = true; 61 inque[sx][sy] = true; 62 while(!que.empty()){ 63 Point e = que.front(); 64 que.pop(); 65 inque[e.x][e.y] = false; 66 for(int k = 0; k < 4; k++){ 67 Point eu(e.x + mover[0][k], e.y + mover[1][k]); 68 if(isExeeded(eu)) continue; 69 if(f[e.x][e.y] + cd[e.x][e.y] < f[eu.x][eu.y] || !visited[eu.x][eu.y]){ 70 visited[eu.x][eu.y] = true; 71 f[eu.x][eu.y] = f[e.x][e.y] + cd[e.x][e.y]; 72 if(!inque[eu.x][eu.y]){ 73 que.push(eu); 74 inque[eu.x][eu.y]= true; 75 } 76 } 77 } 78 } 79 return f[0][0]; 80 } 81 82 inline void init(){ 83 readInteger(n); 84 readInteger(sx); 85 readInteger(sy); 86 for(int i = 1, a, b; i <= n; i++){ 87 readInteger(a); 88 readInteger(b); 89 cd[a][b] = 1; 90 smax(bx, a); 91 smax(by, b); 92 } 93 bx++, by++; 94 } 95 96 inline void solve(){ 97 int result = spfa(); 98 printf("%d", result); 99 } 100 101 int main(){ 102 freopen("tractor.in", "r", stdin); 103 freopen("tractor.out", "w", stdout); 104 init(); 105 solve(); 106 return 0; 107 }
题目描述
Farmer John is building a nicely-landscaped garden, and needs to move alarge amount of dirt in the process.The garden consists of a sequence of N flowerbeds (1 <= N <= 100), whereflowerbed i initially contains A_i units of dirt. Farmer John would liketo re-landscape the garden so that each flowerbed i instead contains B_iunits of dirt. The A_i\'s and B_i\'s are all integers in the range 0..10.To landscape the garden, Farmer John has several options: he can purchaseone unit of dirt and place it in a flowerbed of his choice for $X. He can remove one unit of dirt from a flowerbed of his choice and have it shippedaway for $Y. He can also transport one unit of dirt from flowerbed i toflowerbed j at a cost of $Z times |i-j|. Please compute the minimum totalcost for Farmer John to complete his landscaping project.
输入
第1行:4个整数 N, X, Y, Z (0 <= X, Y, Z <= 1000).
第2..1+N行: 每行2个整数 A_i 和 B_i.
输出
第1行:1个整数,表示最小的花费。
样例输入
4 100 200 1 1 4 2 3 3 2 4 0
样例输出
210
提示
INPUT DETAILS: There are 4 flowerbeds in a row, initially with 1, 2, 3, and 4 units of dirt. Farmer John wishes to transform them so they have 4, 3, 2, and 0 units of dirt, respectively. The costs for adding, removing, and transporting dirt are 100, 200, and 1.
OUTPUT DETAILS: One unit of dirt must be removed (from flowerbed #4), at a cost of 200. The remaining dirt can be moved at a cost of 10 (3 units from flowerbed #4 to flowerbed #1, 1 unit from flowerbed #3 to flowerbed #2).
讲一下题意:
大概就这样子,方法是dp
把A序列和B序列拆成不同的状态,不好直接说,假设A序列是:1 0
就拆成这么几个状态
0 0 1 0
B序列是2 2
0 0 1 0 2 0 2 1 2 2
f[i][j]表示A序列的第i个状态到B序列第j个状态最小的代价
前两种方式可以用如下方式来转移
f[i][j] = min(f[i - 1][j] + y, f[i][j - 1] + x);
(对照着上面两个表看看很容易就能明白,虽然有点绕)
还要考虑记一个位置(看代码),不然无法处理第三种操作
第三种操作相当于将两个已知的位置,一个加1,一个减1,
f[i][j] = min(f[i][j], f[i - 1][j - 1] + z * (a[i] - b[j]));
详情可以参考:http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Dynamic/Edit/
1 #include<iostream> 2 #include<fstream> 3 #include<sstream> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<ctime> 8 #include<cctype> 9 #include<cmath> 10 #include<algorithm> 11 #include<stack> 12 #include<queue> 13 #include<set> 14 #include<map> 15 #include<vector> 16 using namespace std; 17 typedef bool boolean; 18 #define inf 0xfffffff 19 #define smin(a, b) (a) = min((a), (b)) 20 #define smax(a, b) (a) = max((a), (b)) 21 template<typename T> 22 inline void readInteger(T& u){ 23 char x; 24 int aFlag = 1; 25 while(!isdigit((x = getchar())) && x != -1); 26 if(x == -1){ 27 x = getchar(); 28 aFlag = -1; 29 } 30 for(u = x - \'0\'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - \'0\'); 31 ungetc(x, stdin); 32 u *= aFlag; 33 } 34 35 int n; 36 int x, y, z; 37 int f[1010][1010]; 38 int *a, *b; //第i个状态所处位置 39 int ca, cb; //原序列和目标序列的状态数 40 41 int main(){ 42 freopen("landscaping.in", "r", stdin); 43 freopen("landscaping.out", "w", stdout); 44 readInteger(n); 45 readInteger(x); 46 readInteger(y); 47 readInteger(z); 48 49 a = new int[(const int)(n * 10 + 1)]; 50 b = new int[(const int)(n * 10 + 1)]; 51 52 ca = cb = 1; 53 for(int i = 1, j; i <= n; i++){ 54 readInteger(j); 55 while(j > 0) a[ca++] = i, j--; 56 readInteger(j); 57 while(j > 0) b[cb++] = i, j--; 58 } 59 60 for(int i = 1; i < ca; i++) f[i][0] = i * y; 61 for(int i = 1; i < cb; i++) f[0][i] = i * x; 62 63 for(int i = 1; i < ca; i++){ 64 for(int j = 1; j < cb; j++){ 65 f[i][j] = inf; 66 smin(f[i][j], f[i - 1][j] + y); 67 smin(f[i][j], f[i][j - 1] + x); 68 smin(f[i][j], f[i - 1][j - 1] + z * abs(a[i] - b[j])); 69 } 70 } 71 72 printf("%d", f[ca - 1][cb - 1]); 73 return 0; 74 }
描述
明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。
这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?
这个选择题中的每个表达式都满足下面的性质:
1. 表达式只可能包含一个变量‘a’。
2. 表达式中出现的数都是正整数,而且都小于10000。
3. 表达式中可以包括四种运算‘+’(加),‘-’(减),‘*’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘*’,最后 是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)
4. 幂指数只可能是1到10之间的正整数(包括1和10)。
5. 表达式内部,头部或者尾部都可能有一些多余的空格。
下面是一些合理的表达式的例子:
((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9……
对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。
对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。
格式
输入格式
输入的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……
输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。
输出格式
输出包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。
样例输入
( a + 1) ^2 3 (a-1)^2+4*a a + 1+ a a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
样例输出
AC
限制
1s
来源
NOIP2005 第四题
(ps:由于pdf写得太水,所以直接复制vj的:https://vijos.org/p/1003)
正解是将a随便带一个值进去算,mod几个质数,全部都相等才判定为相等
当然我们同学有写200多行多项式乘法AC的(十分膜拜)
我嘛,鉴于整型自带溢出,而且10个点,重复的可能性很小,就把a = -10001带进去算,轻松AC
Code(以前的代码)
1 #include<iostream> 2 #include<cstdio> 3 #include<stack> 4 using namespace std; 5 typedef bool boolean; 6 stack<char> op; 7 stack<long long> num; 8 int n; 9 boolean can(char oper){ 10 if(op.empty()) return false; 11 if(oper==\'(\') return false; 12 if(oper==\')\') return true; 13 char cf=op.top(); 14 if(cf==\'(\') return false; 15 if(cf==oper) return true; 16 if(cf==\')\') return true; 17 if(cf==\'^\'&&oper!=\')\') return true; 18 if(cf==\'*\'&&(oper==\'+\'||oper==\'-\')) return true; 19 if(cf==\'+\'&&oper==\'-\') return true; 20 if(cf==\'-\'&&oper==\'+\') return true; 21 return false; 22 } 23 long long pow(long long n,short int pos){ 24 if(pos==1) return n; 25 if(pos%2==1) return pow(n,pos/2)*pow(n,pos/2)*n; 26 return pow(n,pos/2)*pow(n,pos/2); 27 } 28 long long cale(char oper){ 29 long long result = 0; 30 long long b = num.top(); 31 num.pop(); 32 long long a = num.top(); 33 num.pop(); 34 switch(oper){ 35 case \'+\': 36 result=a+b; 37 break; 38 case \'-\': 39 result=a-b; 40 break; 41 case \'*\': 42 result=a*b; 43 break; 44 case \'^\': 45 result=pow(a,b); 46 break; 47 } 48 op.pop(); 49 return result; 50 } 51 long long getResult(string str){ 52 int index=0; 53 while(index<str.length()){ 54 if(str[index]==\' \'){ 55 index++; 56 continue; 57 } 58 if(index<str.length()&&str[index]>=\'0\'&&str[index]<=\'9\'){ 59 int math = 0; 60 while(index<str.length()&&str[index]>=\'0\'&&str[index]<=\'9\'){ 61 math*=10; 62 math+=str[index]-\'0\'; 63 index++; 64 } 65 num.push(math); 66 continue; 67 } 68 if(index<str.length()&&str[index]==\'a\'){ 69 num.push(-10001); 70 index++; 71 continue; 72 } 73 while(index<str.length()&&(!op.empty())&&can(str[index])){ 74 if(str[index]==\')\'){ 75 while(op.top()!=\'(\') 76 num.push(cale(op.top())); 77 op.pop(); 78 break; 79 }else{ 80 num.push(cale(op.top())); 81 } 82 } 83 if(str[index]!=\')\') 84 op.push(str[index]); 85 index++; 86 } 87 while(!op.empty()){ 88 num.push(cale(op.top())); 89 } 90 long long result=num.top(); 91 num.pop(); 92 return result; 93 } 94 string s; 95 long long answer; 96 int main(){ 97 getline(cin,s); 98 answer=getResult(s); 99 cin>>n; 100 getline(cin,s); 101 for(int i=1;i<=n;i++){ 102 getline(cin,s); 103 if(getResult(s)==answer) cout<<(char)(\'A\'+i-1); 104 } 105 return 0; 106 }
以上是关于[题解]某模拟题(USACO月赛部分题+noip2005部分题)的主要内容,如果未能解决你的问题,请参考以下文章