CKOJ 1066: 地形编辑器(整个区间加减一个数,多次区间操作,处理端点,但这是二维的,骚操作(有dp思想))

1066: 地形编辑器

时间限制: 1 Sec   内存限制: 128 MB
提交: 32   解决: 4
[ 提交][ 状态][ 讨论版]

题目描述

zdw很喜欢玩红警, 他经常制作一些奇奇怪怪的红警地图

当他制作地图的时候, 经常需要用到地形编辑器

zdw可以用这个编辑器将地图上的某个区域的高度改变x来创造地形

一次显然是不够的, 而经过若干次的操作后, 地图上将会出现各种山脉和峡谷

现给出zdw的所有操作, 求这些操作全部完成后地图上每个区块的高度

地图区块的坐标范围为<1,1>,<n,n>

输入数据

  • 第一行两个整数n,m表示地图大小(n*n)和操作数(m)
  • 接下来m行每行5个整数x1,y1,x2,y2,h描述zdw进行的操作
  • 操作的影响为<x1,y1>,<x2,y2>区间内的所有区块的高度改变h
  • 其中当h为正数时表示高度增加, h为负数时表示高度减少

输出数据

  • 共n行,每行n个数, 表示对应的每个区块的最终高度

样例输入

  • 5 3
  • 1 1 2 2 1
  • 2 2 3 4 -2
  • 1 1 4 5 1

样例输出

  • 2 2 1 1 1
  • 2 0 -1 -1 1
  • 1 -1 -1 -1 1
  • 1 1 1 1 1
  • 0 0 0 0 0


输入

输出

提示


对于40%的数据, n<=50,m<=1000



对于70%的数据, n<=1000, m<=10000



对于100%的数据, n<=2000, m<=300000, 1<=x1,y1,x2,y2<=n, -128<=h<=127





来源


思路: 运用了前缀和的思想;处理端点值,但下面是二维的前缀和思想;

首先考虑40%的分数, 显然直接暴力模拟即可, 复杂度O(n2m)

考虑优化, 我们先考虑一维上的做法

假设我们要让[l,r]区间的高度增加h

那么我们可以让A[l]+=h,A[r+1]-=h

之后再做一次前缀和即可求出高度

(因为前缀和是向前求的所以这样操作后正好表示[l,r]区间增高h)

于是我们先把所有操作都放到总区间上然后再求前缀和即可

考虑还原到二维, 我们可以直接把二维分割成一维做, 复杂度O(n2+nm)

此时已经可以通过70%的数据了, 最后的30%怎么做呢?

我们刚刚已经有了先将区间分成两点再计算的思路

所以我们再将二维区间看做一维的一维区间和, 问题就解决了

也就是说我们只要先找到每次操作的左上角(x1,y1),右下角(x2,y2)

然后对四角进行如下操作

A[x1][y1]+=h, A[x1][y2+1]-=h

A[x2+1][y1]-=h, A[x2+1][y2+1]+=h

然后从左上向右下求二维前缀和即可~

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 2020

int n,m;

int a[Max][Max];
int main()
{
	int i,j;
	while(~scanf("%d%d",&n,&m))
	{
		memset(a,0,sizeof(a));
		int x1,y1,x2,y2,tt;
		for(i = 0;i<m;i++)
		{
			scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&tt);
			if(x1>x2) swap(x1,x2);
			if(y1>y2) swap(y1,y2);
			a[x1][y1] += tt;      //处理四个顶点;看看怎么处理四个顶点,看看怎么传值,能达到题目要求; 
			a[x1][y2+1] -= tt;
			a[x2+1][y1] -= tt;
			a[x2+1][y2+1] += tt; 
		}
		for(i = 1;i<=n;i++)
		{
			for(j = 1;j<=n;j++)
			{
				a[i][j+1] += a[i][j];   // 先把当前的值,传给这一行的下一个数 
				a[i][j] += a[i-1][j];   // 再把上一行头顶上的那个值传给当前值;
				//这样就保证了 所有区域都能都会加上的;
				if(j!=1) printf(" ");
				printf("%d",a[i][j]); 
			}
			printf("\n");
		}	
	}
	return 0;
} 

/****************************************************************************************/ /* Compiler.cpp */ /* */ /* Author: Jim Mischel */ /* Description: Dialog and thread code for compiling maps with gbsplib */ /* */ /* The contents of this file are subject to the Genesis3D Public License */ /* Version 1.01 (the "License"); you may not use this file except in */ /* compliance with the License. You may obtain a copy of the License at */ /* http://www.genesis3d.com */ /* */ /* Software distributed under the License is distributed on an "AS IS" */ /* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */ /* the License for the specific language governing rights and limitations */ /* under the License. */ /* */ /* The Original Code is Genesis3D, released March 25, 1999. */ /* Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved */ /* */ /****************************************************************************************/ #include "stdafx.h" #include "compiler.h" #pragma warning(disable : 4201 4214 4115 4514 4711) #include <windows.h> #include <shellapi.h> #pragma warning(default : 4201 4214 4115) #include <assert.h> #include <io.h> #include <fstream.h> #include "filepath.h" #include "consoletab.h" // for ConPrintf (yes, it's ugly) #include "util.h" static CWinThread *CompilerThread = NULL; static HWND hwndThreadParent = NULL; static geBoolean ThreadActive = GE_FALSE; static HINSTANCE GBSPHandle = NULL; static GBSP_FuncHook *GlobalFHook; static ofstream *CompileLog; CompilerErrorEnum Compiler_RunPreview ( char const *PreviewFilename, char const *MotionFilename, char const *GPreviewPath ) { assert (ThreadActive == GE_FALSE); char DestBspName[_MAX_PATH]; { // Verify the .BSP file exists... if (_access (PreviewFilename, 0) != 0) { return COMPILER_ERROR_NOBSP; } } // we're going to copy the preview file to the "levels" subdirectory // of the GPreviewPath directory... // // So, if the PreviewFilename is "C:\MyStuff\MyLevel.bsp", // and GPreviewPath is "C:\Editor\GPreview.exe", then the resulting // file name is "C:\Editor\levels\MyLevel.bsp" // { /* char PreviewDrive[_MAX_PATH]; char PreviewDir[_MAX_PATH]; char Name[_MAX_PATH]; char Ext[_MAX_PATH]; _splitpath (PreviewFilename, NULL, NULL, Name, Ext); _splitpath (GPreviewPath, PreviewDrive, PreviewDir, NULL, NULL); strcat (PreviewDir, "media\\levels\\"); _makepath (DestBspName, PreviewDrive, PreviewDir, Name, Ext); */ // make dest path same as source path strcpy(DestBspName, PreviewFilename); } // if source and destination are the same, then don't copy... if (stricmp (DestBspName, PreviewFilename) != 0) { if(!CopyFile (PreviewFilename, DestBspName, FALSE)) { int LastError; LastError = GetLastError(); if (LastError != ERROR_FILE_EXISTS) { ConPrintf("GPreviewPath: %s \n", GPreviewPath); ConPrintf("CopyFile (%s, %s)\nGetLastError()==%d\n", PreviewFilename, DestBspName, LastError); return COMPILER_ERROR_BSPCOPY; } } } { // copy the motion file if it exists char DestName[_MAX_PATH]; // check to see if the file exists FilePath_SetExt (DestBspName, ".mot", DestName); if (_access (MotionFilename, 0) == 0) // _access returns 0 on success...of course! { if (stricmp (MotionFilename, DestName) != 0) { if (!CopyFile (MotionFilename, DestName, FALSE)) { if(GetLastError() != ERROR_FILE_EXISTS) { ConPrintf ("%s", "Unable to copy the motion file.\n"); ConPrintf ("%s", "Continuing with preview.\n"); } } } } else { _unlink (DestName); } } { SHELLEXECUTEINFO shx; char Params[_MAX_PATH]; char DefaultDir[_MAX_PATH]; char NoExtName[_MAX_PATH]; FilePath_GetDriveAndDir (GPreviewPath, DefaultDir); FilePath_GetName (DestBspName, NoExtName); sprintf (Params, "-map %s", NoExtName); shx.fMask = 0; shx.hwnd = NULL; //(HWND)AfxGetMainWnd(); shx.lpVerb = NULL; shx.lpFile = GPreviewPath; shx.lpParameters= Params; shx.lpDirectory = DefaultDir; shx.nShow = SW_NORMAL; shx.hInstApp = NULL; shx.cbSize = sizeof(shx); ShellExecuteEx(&shx;); } return COMPILER_ERROR_NONE; } geBoolean Compiler_CancelCompile ( void ) { if (!ThreadActive) { return GE_FALSE; } return GlobalFHook->GBSP_Cancel (); } static CompilerErrorEnum Compiler_LoadCompilerDLL ( GBSP_FuncHook **ppFHook, HINSTANCE *pHandle, ERROR_CB ErrorCallbackFcn, PRINTF_CB PrintfCallbackFcn ) { GBSP_INIT *GBSP_Init; GBSP_Hook Hook; GBSP_FuncHook *FHook; assert (ppFHook != NULL); assert (pHandle != NULL); *ppFHook = NULL; Hook.Error = ErrorCallbackFcn; Hook.Printf = PrintfCallbackFcn; GBSPHandle = LoadLibrary("gbsplib.dll"); if (GBSPHandle == NULL) { PrintfCallbackFcn ("Compile Failed: Unable to load gbsplib.dll!\nGetLastError returned %d.\n", GetLastError ()); return COMPILER_ERROR_NODLL; } GBSP_Init =(GBSP_INIT*)GetProcAddress(GBSPHandle, "GBSP_Init"); if (GBSP_Init == NULL) { PrintfCallbackFcn ("%s", "Compile Failed: Couldn't initialize GBSP_Init, GBSPLib.Dll.\n."); FreeLibrary(GBSPHandle); return COMPILER_ERROR_MISSINGFUNC; } FHook = GBSP_Init (&Hook;); if (FHook == NULL) { PrintfCallbackFcn ("%s", "Compile Failed: GBSP_Init returned NULL Hook!, GBSPLib.Dll.\n."); FreeLibrary(GBSPHandle); return COMPILER_ERROR_MISSINGFUNC; } if(FHook->VersionMajor > GBSP_VERSION_MAJOR) { PrintfCallbackFcn ("%s", "Compile Failed: GBSP Version Incompatible, GBSPLib.Dll.\n."); FreeLibrary (GBSPHandle); return COMPILER_ERROR_MISSINGFUNC; } *ppFHook = FHook; *pHandle = GBSPHandle; return COMPILER_ERROR_NONE; } CompilerErrorEnum Compiler_Compile ( CompileParamsType const *pParams, ERROR_CB ErrorCallbackFcn, PRINTF_CB PrintfCallbackFcn ) { HINSTANCE GBSPHandle; CompilerErrorEnum CompileRslt; GBSP_RETVAL GbspRslt; char BspFilename[_MAX_PATH]; char MotionFilename[_MAX_PATH]; // load compiler DLL CompileRslt = Compiler_LoadCompilerDLL (&GlobalFHook;, &GBSPHandle;, ErrorCallbackFcn, PrintfCallbackFcn); if (CompileRslt == COMPILER_ERROR_NONE) { FilePath_SetExt (pParams->Filename, ".bsp", BspFilename); FilePath_SetExt (pParams->Filename, ".mot", MotionFilename); if (pParams->EntitiesOnly) { #if 1 #pragma message ("Should UpdateEntities return a GBSP_RETVAL?") if (GlobalFHook->GBSP_UpdateEntities ((char *)pParams->Filename, BspFilename)) { GbspRslt = GBSP_OK; } else { GbspRslt = GBSP_ERROR; } #else GbspRslt = GlobalFHook->GBSP_UpdateEntities ((char *)pParams->Filename, BspFilename); #endif switch (GbspRslt) { case GBSP_ERROR: PrintfCallbackFcn ("%s", "Compile Failed: GBSP_UpdateEntities returned an error. GBSPLib.Dll.\n"); CompileRslt = COMPILER_ERROR_BSPFAIL; break; case GBSP_OK : break; case GBSP_CANCEL : PrintfCallbackFcn ("%s", "UpdateEntities cancelled by user.\n"); CompileRslt = COMPILER_ERROR_USERCANCEL; break; default : assert (0); } } else if (pParams->RunBsp) { _unlink (MotionFilename); // gotta make sure this doesn't exist... GbspRslt = GlobalFHook->GBSP_CreateBSP ((char *)pParams->Filename, (BspParms *)&pParams;->Bsp); switch (GbspRslt) { case GBSP_ERROR : PrintfCallbackFcn ("%s", "Compile Failed: GBSP_CreateBSP encountered an error, GBSPLib.Dll.\n."); CompileRslt = COMPILER_ERROR_BSPFAIL; break; case GBSP_OK : //save as a bsp GbspRslt = GlobalFHook->GBSP_SaveGBSPFile(BspFilename); switch (GbspRslt) { case GBSP_ERROR : PrintfCallbackFcn ("Compile Failed: GBSP_SaveGBSPFile for file: %s, GBSPLib.Dll.\n.", BspFilename); CompileRslt = COMPILER_ERROR_BSPSAVE; break; case GBSP_CANCEL : PrintfCallbackFcn ("%s", "Save cancelled by user\n"); CompileRslt = COMPILER_ERROR_USERCANCEL; break; case GBSP_OK : break; default : assert (0); } break; case GBSP_CANCEL : PrintfCallbackFcn ("%s", "Compile cancelled by user\n"); CompileRslt = COMPILER_ERROR_USERCANCEL; break; default : assert (0); //?? } GlobalFHook->GBSP_FreeBSP(); } } if (CompileRslt == COMPILER_ERROR_NONE) { if(pParams->DoVis && !pParams->EntitiesOnly) { GbspRslt = GlobalFHook->GBSP_VisGBSPFile ((char *)BspFilename, (VisParms *)&pParams;->Vis); switch (GbspRslt) { case GBSP_ERROR : PrintfCallbackFcn ("Warning: GBSP_VisGBSPFile failed for file: %s, GBSPLib.Dll.\n.", BspFilename); break; case GBSP_CANCEL : PrintfCallbackFcn ("%s", "GBSP_VisGBPSFile cancelled by user\n"); CompileRslt = COMPILER_ERROR_USERCANCEL; break; case GBSP_OK : break; default : assert (0); } } } if (CompileRslt == COMPILER_ERROR_NONE) { if (pParams->DoLight) { /* The compiler has no flag that tells it not to do min lighting. So, if the min lighting flag is not on, we set the MinLight vector to all 0s. */ LightParms rad; rad = pParams->Light; if (!pParams->UseMinLight) { geVec3d_Set (&rad;.MinLight, 0.0f, 0.0f, 0.0f); } // If UseMinLight isn't on, then don't pass GbspRslt = GlobalFHook->GBSP_LightGBSPFile(BspFilename, &rad;); switch (GbspRslt) { case GBSP_ERROR : PrintfCallbackFcn ("Warning: GBSP_LightGBSPFile failed for file: %s, GBSPLib.Dll.\n", BspFilename); break; case GBSP_CANCEL : PrintfCallbackFcn ("%s", "GBSP_LightGBSPFile cancelled by user\n"); CompileRslt = COMPILER_ERROR_USERCANCEL; break; case GBSP_OK : break; default : assert (0); } } } // and free the DLL... if (GBSPHandle != NULL) { FreeLibrary (GBSPHandle); } return CompileRslt; } static void Compiler_NotifyApp ( char const *buf, int MsgId ) { #if 1 char *errmsg; errmsg = Util_Strdup (buf); if (errmsg != NULL) { ::PostMessage (hwndThreadParent, MsgId, COMPILER_PROCESSID, (LPARAM)errmsg); } #else ConPrintf ("%s", buf); #endif } static void Compiler_PrintfCallback ( char *format, ... ) { va_list argptr; char buf[32768]; //this is ... cautious va_start (argptr, format); vsprintf (buf, format, argptr); va_end (argptr); if (CompileLog) (*CompileLog) << buf; Compiler_NotifyApp (buf, WM_USER_COMPILE_MSG); } static void Compiler_ErrorCallback ( char *format, ... ) { va_list argptr; char buf[32768]; //this is ... cautious va_start (argptr, format); vsprintf (buf, format, argptr); va_end (argptr); if (CompileLog) (*CompileLog) << buf; Compiler_NotifyApp (buf, WM_USER_COMPILE_ERR); } static UINT Compiler_ThreadProc ( void *pParam ) { CompileParamsType CompileParams; CompilerErrorEnum CompileRslt; assert (pParam != NULL); assert (ThreadActive == GE_FALSE); ThreadActive = GE_TRUE; CompileParams = *((CompileParamsType *)pParam); char LogFilename[_MAX_PATH]; FilePath_SetExt(CompileParams.Filename, ".log", LogFilename); CompileLog = new ofstream(LogFilename, ofstream::out | ofstream::trunc); CompileRslt = Compiler_Compile (&CompileParams;, Compiler_ErrorCallback, Compiler_PrintfCallback); if (CompileRslt == COMPILER_ERROR_NONE) { Compiler_PrintfCallback ("%s", "------------------------------\n"); Compiler_PrintfCallback ("%s", "Compile successfully completed\n"); } if (CompileLog) { (*CompileLog).close(); delete CompileLog; } // notify parent that the compile has completed ::PostMessage (hwndThreadParent, WM_USER_COMPILE_DONE, COMPILER_PROCESSID, (LPARAM)CompileRslt); ThreadActive = GE_FALSE; return 0; } CompilerErrorEnum Compiler_StartThreadedCompile ( CompileParamsType const *pParams, HWND hwndNotify ) { CWinThread *Thread; assert (ThreadActive == GE_FALSE); hwndThreadParent = hwndNotify; Thread = AfxBeginThread ( Compiler_ThreadProc, // AFX_THREADPROC pfnThreadProc, (LPVOID)pParams, // LPVOID pParam, THREAD_PRIORITY_NORMAL, // int nPriority = THREAD_PRIORITY_NORMAL, 0, // UINT nStackSize = 0, 0, // DWORD dwCreateFlags = 0, NULL // LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); if (Thread != NULL) { CompilerThread = Thread; return COMPILER_ERROR_NONE; } else { return COMPILER_ERROR_THREAD; // couldn't spawn the thread } } geBoolean Compiler_CompileInProgress ( void ) { return ThreadActive; }
作品名称 游戏地图编辑器 作者 汉克斯 运行环境 只在Win XP Service Pack2的环境下测试 联系方式 QQ: 349330748 源代码使用的编译器 VS2005 代码说明 此编辑器是用自行写的库制作的,库可实现45度和0度2D的绘制,里面包含简单的效果模块,还有比较失败的控件模块, 都是可以自行扩展的. 由于这是个demo,并没有把使用的资源放在特定的文档里面,而是集成在程序内部成了硬编码,的确不太方便.这里,感 谢不夜人的图片资源,给我省掉了很多的事情. 另外说明,代码的编写基本上是一个人完成的,完全使用其他人代码的地方,我都在SDK中进行了说明,如果想获取此程 序的SDK,请联系我.或者你可以自行制作出SDK,使用doxygen根据代码可自动生成SDK. 程序说明 编辑器可在16位和32位颜色模式下运行(24位不行!)。 可对地面建筑和精灵进行添加、删除、移动、修改等操作。 对地图进行的添加、删除、移动等操作会被存入缓存,以供Redo、Undo。 可显示地图网格和地面是否能通过的情况。 对精灵可以以加速、减速、暂停等速度方式运行。 其他使用说明请使用程序内部的"说明"按钮 后记 这个程序是对C++和Ddraw库学习的一个总结,由于windows的编程设计还刚开始学,所以其中的有些部分可能是费力不 讨好的(控件部分),有些部分是没有深入使用的(多线程部分),不过目前是基本满意了.希望大家也帮忙测试一下,有 bug的话通知我一声,我对于在其他的电脑上运行是怎样的还没有个底,先谢过了.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值