USACO US OPEN 2015 BRONZE 三四题 C++翻译代码

来源:互联网 发布:java数组去重的方法 编辑:程序博客网 时间:2024/05/29 08:57
应江老师的要求,我将官方结题报告中的三、四题的java代码翻译成了C++。顺便还将注释翻译成了中文。但是还没有检查。

3、
注:该题检查已过。

# include <cstdio>
# include <algorithm>
using namespace std;
const int MAXN = 4001;
struct Haybale{
int position;
int size;
};

//按坐标的先后排序
int cmp(Haybale a,Haybale b){
return a.position < b.position;
}
int n;
Haybale bales[MAXN];

int main(){
scanf("%d",&n);
for (int i=0;i!=n;++i){
scanf("%d %d",&bales[i].size,&bales[i].position);
}

sort(bales+0,bales+n,cmp);//排序以离散化

int ans = 0;
for (int i=0;i!=n-1;++i){
int areaOfInterval = bales[i+1].position - bales[i].position;//当前所能达到的区域
int leftmostBale = i;//左边能走得最远的地方
int rightmostBale = i+1;//右边能走得最远的地方
while (leftmostBale >= 0 && rightmostBale <= n-1){//继续条件:没有在左右其中一个方向能出去
bool broke = false;//broke是标志 :能否破开
int currDist = bales[rightmostBale].position - bales[leftmostBale].position;
//currDist指前后所能达到的最远的地方(当前已经破开草堆的中间的空间)
if (currDist > bales[leftmostBale].size){
//能破开左边的草堆
--leftmostBale;
broke = true;
}
if (currDist > bales[rightmostBale].size){
//能破开右边的草堆
++rightmostBale;
broke = true;
}
if (!broke){
//没能破开就不能搜下去了
break;
}
}

if (leftmostBale >= 0 && rightmostBale <= n-1){
//若没有能够破开
ans += areaOfInterval;
}
}
//这个程序的思想就是不断地往左右两边扩展,
//直到能够达到破开的最大限度

//输出答案
printf("%d\n",ans);
}



4、
注:该题检查已过。
# include <algorithm>
# include <string>
# include <cstdio>
# include <set>
using namespace std;
const int MAXN = 20;
set<string> rows1[MAXN],rows2[MAXN];
set<string> ans;
char grid[MAXN][MAXN];
int n;

//dfs()就是一个深搜的函数,将路上经过的字符串放入集合内
//注意遇到对角线即停止
void dfs(int x,int y,set<string> sets[],string curr){
if (x + y == n - 1){
sets[x].insert(curr + grid[x][y]);
}
else{
dfs(x+1,y,sets,curr+grid[x][y]);
dfs(x,y+1,sets,curr+grid[x][y]);
}
}

//transpose()函数将原来grid[][]的上下左右反转
void transpose(){
for (int i=0;i<n;++i){
for (int j=0;j<n;++j){
if (i+j >= n-1) continue;
swap(grid[i][j],grid[n-i-1][n-j-1]);
}
}
}

int main(){
scanf("%d",&n);
for (int i=0;i<n;++i){
for (int j=0;j<n;++j){
scanf("%c",&grid[i][j]);
if (grid[i][j] == '\n'){
scanf("%c",&grid[i][j]);
}
}
}

//rows1指的是从左上角开始到中间对角线的所有字符串的集合
//rows2指的是从右下角开始的所有字符串集合

//从左上角开始进行深搜,将所有字符串放入rows1中
dfs(0,0,rows1,"");
//上下左右对调
transpose();
//这里是从左上角,但放到原来而言,是从右下角
//这是为了避免另一个问题,下面会讲到
dfs(0,0,rows2,"");

//在这里其实做的是rows1和rows2的并集
//但是rows1是从左上角开始的,rows2是从右下角开始的,会不会因顺序不一样而找不到呢?
//答案是不会的,因为上面已经用transpose()将其反转
set<string>::iterator it;
for (int i=0;i<n;++i){
for (it = rows1[i].begin();it != rows1[i].end();++it){
if (rows2[i].count(*it)){
ans.insert(*it);
}
}
}
//所以这个程序的思想就是枚举每一个字符串,放到集合中(注意是集合,不会有重复的元素)
//最后输出两边开始的所有字符串的集合的并的大小,就肯定是一个回文字符串了
printf("%d\n",ans.size());
}
0 0