目录
A:计算两个日期之间的天数【暴力不水】
B:回文子串【暴力不水】
C:The Die Is Cast【DFS】
D:Euro Efficiency【看不懂】
E:重要逆序对【归并排序】
F:Tram【看不懂】
G:食物链【图】
H:DFS spanning tree【不会】
A:计算两个日期之间的天数【暴力不水】
//http://bailian.openjudge.cn/xly2018/A/
#include<iostream>
using namespace std;
int main(){
int a[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int sy,sm,sd;
int ey,em,ed;
int sum=0,sum1=0;
cin>>sy>>sm>>sd;
cin>>ey>>em>>ed;
for(int i=1;i<sy;i++){
sum+=365;
if(i%4==0&&i%100!=0||i%400==0)
sum++;
}
for(int i=1;i<sm;i++){
sum+=a[i];
if(i==2&&(sy%4==0&&sy%100!=0||sy%400==0))
sum++;
}
sum+=sd;
for(int i=1;i<ey;i++){
sum1+=365;
if(i%4==0&&i%100!=0||i%400==0)
sum1++;
}
for(int i=1;i<em;i++){
sum1+=a[i];
if(i==2&&(ey%4==0&&ey%100!=0||ey%400==0))
sum1++;
}
sum1+=ed;
cout<<sum1-sum<<endl;
return 0;
}
B:回文子串【暴力不水】
这个题做了好久……我是傻逼
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
char jiequ[100];
bool huiwen(string a){
int len=a.length();
int maxx=1;
int flag=1;
for(int i=0;i<len/2+1;i++){
if(a[i]!=a[len-i-1]) flag=0;
}
if(flag==0) return 0;
return 1;
}
int main(){
int n;
cin>>n;
string ch;
for(int i=0;i<n;i++){
cin>>ch;
int lenn=ch.length();
int temp=lenn;
int flag=0;
for(int temp=lenn;temp>0;temp--){
if(flag==1) break;
for(int j=0;j<=lenn-temp;j++){
string jiequ=ch.substr(j,temp);
// cout<<jiequ<<endl;
if(huiwen(jiequ)) {
cout<<jiequ<<endl;
flag=1;
break;
}
}
}
}
return 0;
}
C:The Die Is Cast【DFS】
(1条消息) 【做练习】The Die Is Cast (搜索)_混沌神选韭菜的博客-CSDN博客
需要两层不同的dfs。第一个dfs搜连通的非背景点,而当它发现了一个新的骰子点上的像素时,调用第二层dfs。第二层dfs负责搜连通的骰子点像素。
看不懂了 谢谢
#include<iostream>
#include<algorithm>
using namespace std;
enum class Pixel: unsigned char {
Background,
Die,
DieDot
};
void DfsDie(int i, int j, int index);
void DfsDieDot(int i, int j, int index);
int w, h;
Pixel img[64][64];
bool visited[64][64];
bool visited_dieDot[64][64];
int cnt[500];
int nDie;
// 从一个像素点开始,遍历它所在的骰子
// index 为骰子的序号
void DfsDie(int i, int j, int index){
if (i < 0 || j < 0 || i >= h || j >= w || visited[i][j] || img[i][j] == Pixel::Background) return;
visited[i][j] = true;
DfsDie(i - 1, j, index);
DfsDie(i + 1, j, index);
DfsDie(i, j - 1, index);
DfsDie(i, j + 1, index);
if (img[i][j] == Pixel::DieDot && !visited_dieDot[i][j]) {
cnt[index]++;
DfsDieDot(i, j, index);
}
}
// 从一个像素点开始,遍历它所在的骰子的点
void DfsDieDot(int i, int j, int index) {
if (i < 0 || j < 0 || i >= h || j >= w || visited_dieDot[i][j]
|| img[i][j] != Pixel::DieDot) return;
visited_dieDot[i][j] = true;
DfsDieDot(i - 1, j, index);
DfsDieDot(i + 1, j, index);
DfsDieDot(i, j - 1, index);
DfsDieDot(i, j + 1, index);
}
int main(){
int nThrow = 0;
while (++nThrow) {
cin >> w >> h;
if (w == 0 && h == 0) break;
cin.get();
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
char ch = cin.get();
img[i][j] = ch == '*' ? Pixel::Die : (ch == 'X' ? Pixel::DieDot : Pixel::Background);
}
cin.get();
}
// init
nDie = 0;
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++)
visited[i][j] = visited_dieDot[i][j] = 0;
for (int i = 0; i < 500; i++) cnt[i] = 0;
// 遍历、搜索
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++) {
if (img[i][j] != Pixel::Background && ! visited[i][j]) DfsDie(i, j, nDie++);
}
// 排序
sort(cnt, cnt + nDie);
// 输出
cout << "Throw " << nThrow << '\n';
for (int i = 0; i < nDie; i++)
cout << cnt[i] << (i == nDie - 1 ? '\n' : ' ');
cout << endl;
}
return 0;
}
D:Euro Efficiency【看不懂】
E:重要逆序对【归并排序】
参考:归并排序方法解决重要逆序对问题
/*
#include<iostream>
using namespace std;
int a[10000000];
int sum;
int main(void){
int N;
cin>>N;
for(int i=0;i<N;i++){
cin>>a[i];
}
for(int i=0;i<N-1;i++){
for(int j=i+1;j<N;j++){
if(a[i]>2*a[j]) sum++;
}
}
cout<<sum;
}
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 200010;
int array[maxn], temp[maxn];
long long ans = 0; // 存储逆序对个数,使用long long 总数能够超过int范围
void merge(int left, int mid, int right) // 归并函数
{
int i = left; // 左边数组的起始位置
int j = mid + 1; // 右边数组的起始位置
int pos = left; // 递增的计数器,用于存储合并后的结果
// 计算“重要逆序对”时不能像“逆序对”那样,将计数嵌入到归并过程当中去,会改变时间复杂度超过O(nlogn)
while(i <= mid && j <= right)
{
if(array[i] <= 2 * array[j]) // 不满足重要逆序对条件
{
i++; // 左边元素不需要与右边元素进行比较
}
else
{
j++; // 右边元素满足重要逆序对条件,继续查找下一个右边元素
ans += mid - i + 1; // 计数 i已经满足逆序条件了,所以左半部分i还没比较的肯定也满足,所以加上这些个玩意
}
}
i = left, j = mid + 1, pos = left; // 恢复初始
while(i <= mid && j <= right) // 从小到大排序存储
{
if(array[i] <= array[j]) // 左边元素小于等于右边元素
{
temp[pos++] = array[i++]; // 存储左边元素
}
else
{
temp[pos++] = array[j++]; // 存储右边元素
// ans += mid-i+1; // 在“逆序对”中,直接在这里计数就好
}
}
while(i <= mid) // 将剩下的左边元素存储到temp数组中
{
temp[pos++] = array[i++];
}
while(j <= right) // 将剩下的右边元素存储到temp数组中
{
temp[pos++] = array[j++];
}
for(int i = left; i <= right; i++) // 将temp数组中的结果复制回array数组
{
array[i] = temp[i];
}
}
void mergesort(int left, int right) // 归并排序函数
{
if(left < right) // 当left小于right时,继续分割数组
{
int mid = (left + right) / 2; // 分割数组的中间位置
mergesort(left, mid); // 对左边数组继续递归排序
mergesort(mid + 1, right); // 对右边数组继续递归排序
merge(left, mid, right); // 合并左右数组
}
}
int main()
{
// freopen("input.txt", "r", stdin); // 打开输入文件
int n;
scanf("%d", &n); // 输入数组大小
for(int i = 0; i < n; i++)
{
scanf("%d", &array[i]); // 输入数组元素
}
mergesort(0, n - 1); // 归并排序
printf("%lld", ans); // 输出逆序对个数
// fclose(stdin); // 关闭输入文件
return 0;
}
上面注释掉的暴力行不通哦,时间复杂度太太太高了