Zhejiang Provincial Programming Contest 2007 部分题解

本文深入探讨了优先队列、广度优先搜索、动态规划等算法在解决AAttackOfPandaVirus问题中的应用,同时展示了字符串处理、动态规划解决水问题,以及动态规划在DeckofCards游戏中的策略实现。文章还涵盖了从优先队列到矩阵乘法的算法技巧,提供了高效求解策略。此外,通过实验和实例,展示了如何利用算法优化和数据结构设计来提升程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AAttack of Panda Virus    

优先队列 + bfs

可以根据def 和 到可能到达此处的病毒等级为元素进行排列

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
using namespace std;
const int LMT = 250003;
int have[LMT], vis[502][502],cnt;
int gra[502][502];
map<int, int> lev_mp;
struct __node
{
    int d, lev, posi, posj, mlev;
    __node(){}
    __node(int a, int b, int c, int i, int j)
    : d(a), lev(b), mlev(c), posi(i), posj(j){}
    bool operator > (const __node &y)
    {
        if(d != y.d) return d > y.d;
        return lev > y.lev;
    }
};
struct cmp
{
    bool operator ()(__node a, __node b)
    {
        return a > b;
    }
};
priority_queue<__node, vector<__node>, cmp> que;
void init(void)
{
    cnt = 0;
    while(!que.empty())que.pop();
    lev_mp.clear();
    memset(vis, 0, sizeof(vis));
    memset(have, 0, sizeof(have));
}
int main(void)
{
    int n, m, alf, temi, temj;
    __node from, to;
    while(~scanf("%d%d", &n, &m))
    {
        init();
        alf = 0;
        for(int i = 0; i < n; ++i)
          for(int j = 0; j < m; ++j)
          {
             scanf("%d", &gra[i][j]);
             if(gra[i][j] > 0)
             {
               if(lev_mp.find(gra[i][j]) == lev_mp.end())
               {
                   lev_mp.insert(make_pair(gra[i][j], cnt));
                   que.push(__node(0, gra[i][j], cnt, i, j));
                   ++cnt;
               }
             }
          }
          while(!que.empty())
          {
              from = que.top();
              temi = que.top().posi;
              temj = que.top().posj;
              que.pop();
              if(vis[temi][temj])continue;
              vis[temi][temj] = 1;
              ++have[from.mlev];
              ++alf;
              if(alf >= n * m) break;
              if(temi > 0 && 0 == vis[temi - 1][temj])
              {
                  if(gra[temi - 1][temj] < 0)
                  que.push
                  (
                  __node(-gra[temi - 1][temj],
                    from.lev, from.mlev,temi - 1, temj));
              }
              if(temj >0 && 0 == vis[temi][temj - 1])
              {
                  if(gra[temi][temj - 1] < 0)
              que.push
              (
              __node(-gra[temi][temj - 1],
               from.lev, from.mlev, temi, temj - 1));
              }
               if(temi < n - 1 && 0 == vis[temi + 1][temj])
               {
                   if(gra[temi + 1][temj] < 0)
               que.push
               (
               __node(-gra[temi + 1][temj],from.lev, from.mlev, temi + 1, temj));
               }
               if(temj < m - 1 && 0 == vis[temi][temj + 1])
               {
                   if(gra[temi][temj + 1] < 0)
               que.push
               (
               __node(-gra[temi][temj + 1],from.lev, from.mlev, temi, temj + 1));
               }
          }
          int q, ql;
          scanf("%d", &q);
          while(q--)
          {
              scanf("%d", &ql);
              if(lev_mp.find(ql) != lev_mp.end())
              printf("%d\n", have[lev_mp[ql]]);
              else printf("0\n");
          }
    }
    return 0;
}

B 水

Code Formatter

字符串处理,WA了好多次, 注意终止条件是一行“只含有”两个‘#’

#include <cstdio>
#include <cstring>
const int LMT = 102;
char sec[LMT];
int main(void)
{
	int i,tab, tail, T, len;
	scanf("%d", &T);
	getchar();
	while(T--)
	{
		tab = 0; tail = 0;
		while(gets(sec))
		{
			len = strlen(sec);
			if(len == 2 && sec[0] == '#' && sec[1] == '#') break;
			for(i = len - 1; i >= 0; --i)
				if (sec[i] == ' ')
					++tail;
				else if(sec[i] == '\t')
					tail +=4;
				else break;
            for(i = 0; i < len; ++i)
				if(sec[i] == '\t')
					++tab;
		}
		printf("%d tab(s) replaced\n%d trailing space(s) removed", tab, tail);
		if (T) printf("\n"); 
	}
	return 0;
}

Deck of Cards 

水的动态规划, 当前的状态是选择哪一个洞, 注意当一个洞放上F或上面的牌点数总和等于21时,有额外积分,并且可以把上面的牌都拿掉

#include <cstdio>
#include <cstring>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
const int LMT = 23;
int dp[103][LMT][LMT][LMT];
int vn[103];
int main(void)
{
	int val[100], n, i, x, y, z, tem, ans;
	char ch;
	val['A'] = 1; val['6'] = 6;
	val['2'] = 2; val['7'] = 7;
	val['3'] = 3; val['8'] = 8;
	val['4'] = 4; val['9'] = 9;
	val['5'] = 5; val['T'] = 10;
	val['J'] = 10; val['Q'] = 10;
	val['K'] = 10; val['F'] = 22;
	while(~scanf("%d", &n) && n)
	{
		memset(dp, -1 , sizeof(dp));
		ans = -1;
		dp[0][0][0][0] = 0;
		for(i = 1; i <= n; ++i)
		{
			ch = getchar();
			while(ch == ' ' || ch == '\n')
				ch = getchar();
			vn[i] = val[ch];
		}
		for(i = 1; i <= n; ++i)
		{
			for(x = 0; x <= 22; ++x)
				for(y = 0; y <= 22; ++y)
					for(z = 0; z <= 22; ++z)
						if(dp[i - 1][x][y][z] != -1)
						{
							if(x < 22)
							{
								tem = x + vn[i];
								if(tem > 22) tem =22;
								if(tem == 21 || vn[i] == 22) tem =0;
								if(tem)
								   dp[i][tem][y][z] = max(dp[i][tem][y][z], dp[i - 1][x][y][z] + 50);
								else dp[i][tem][y][z] = max(dp[i][tem][y][z], dp[i - 1][x][y][z] + 150);
								if(i == n || tem >=22 || y >= 22 || z >= 22)
									ans = max(ans, dp[i][tem][y][z]);
							}
							if(y < 22)
							{
								tem = y + vn[i];
								if(tem > 22) tem =22;
								if(tem == 21 || vn[i] == 22) tem =0;
								if(tem)
								  dp[i][x][tem][z] = max(dp[i][x][tem][z], dp[i - 1][x][y][z] + 50);
								else dp[i][x][tem][z] = max(dp[i][x][tem][z], dp[i - 1][x][y][z] + 250);
								if(i == n || x >=22 || tem >= 22 || z >= 22)
									ans = max(ans, dp[i][x][tem][z]);
							}
							if(z < 22)
							{
								tem = z + vn[i];
								if(tem > 22) tem =22;
								if(tem == 21 || vn[i] == 22) tem =0;
								if(tem)
								dp[i][x][y][tem] = max(dp[i][x][y][tem], dp[i - 1][x][y][z] + 50);
								else dp[i][x][y][tem] = max(dp[i][x][y][tem], dp[i - 1][x][y][z] + 350);
								if(i == n || x >=22 || y >= 22 || tem >= 22)
									ans = max(ans, dp[i][x][y][tem]);
							}
						}
		}
		printf("%d\n", ans);
	}
	return 0;
}

E 矩阵乘法,小心点就好了

F 计算几何, 不会啊...

G google map 

因为远点计算出错,卡了...

#include<cstdio>
#include<cmath>
#define eps 1e-9
const long double pi = acos(-1);
inline double lab_mid(double l, double r)
{
	double tem = atan(
   sqrt(tan(pi / 4 + (l * pi / 180) / 2) *
              tan(pi / 4 + (r * pi / 180) / 2))
		);
	return (tem - pi/4) * 2 * 180 / pi;
}
int main(void)
{
	double loq, laq, lab, lob;
	double lau, lad, lol, lor, temlo, temla;
	char tag;
	int L;
	while(~scanf("%lf%lf%d", &loq, &laq, &L))
	{
	    temla = temlo = lob = lab = 0.0;
		lol = -180.0; lor = 180.0;
		lau = 85; lad = -85;
		printf("t");
		for(int i = 1; i <=L; ++i)
		{
			if(loq > lob&& laq > lab)
			{
				tag = 'r';
				lob = (lob + lor)*0.5;
				lab = lab_mid(lab, lau);
				lol = temlo; lor = lor;
				lad = temla; lau = lau;
			}
			else if(loq > lob && laq < lab)
			{
				tag = 's';
				lob = (lob + lor)*0.5;
				lab = lab_mid(lad, lab);
				lol = temlo; lor = lor;
				lad = lad; lau = temla;
			}
			else if(loq < lob && laq > lab)
			{
				tag = 'q';
				lob = (lob + lol) * 0.5;
				lab = lab_mid(lab, lau);
				lol = lol; lor = temlo;
				lad = temla; lau = lau;
			}
			else if(loq < lob && laq < lab)
			{
				tag = 't';
				lob = (lob + lol) * 0.5;
				lab = lab_mid(lad, lab);
				lol = lol; lor = temlo;
				lad = lad; lau = temla;
			}
			printf("%c", tag);
			temlo = lob;
			temla = lab;
		}
		printf("\n");
	}
	return 0;
}


内容概要:《学术研究提示设计 50 招》是一份详尽的指南,旨在帮助研究人员提高学术写作和研究效率。该文档涵盖了从论文撰写、润色、翻译、查重降重、参考文献管理、投稿审稿到文献阅读等多个方面的具体操作指令。每一章节均针对特定任务提供了详细的步骤和注意事项,例如如何撰写标题、摘要、致谢,如何进行英文润色、中英翻译,以及如何优化逻辑结构等。文档还介绍了如何利用AI工具进行文献分析、术语表提取和研究方向探索等内容,为研究者提供了全面的支持。 适合人群:适用于学术研究人员,特别是那些需要撰写、润色和提交学术论文的研究者,包括研究生、博士生及高校教师等。 使用场景及目标:① 提供一系列具体的指令,帮助研究者高效完成论文的各个部分,如撰写标题、摘要、致谢等;② 提供润色和翻译的详细指导,确保论文语言的准确性和专业性;③ 提供查重降重的方法,确保论文的原创性;④ 提供参考文献管理和投稿审稿的指导,帮助研究者顺利发表论文;⑤ 利用AI工具进行文献分析、术语表提取和研究方向探索,提高研究效率。 阅读建议:此资源不仅提供了具体的指令和方法,更重要的是引导研究者如何思考和解决问题。因此,在学习过程中,不仅要关注具体的步骤,还要理解背后的原理和逻辑,结合实际案例进行实践和反思。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值