2018南京

Magical Girl Haze

bfs记忆化搜索
设dis[v][c]是走到v点,用掉了c次机会的最短路距离,比最短路问题多了一维
exd记录已经被扩展过的状态
#include<bits/stdc++.h>
#define RD1(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d %d",&x,&y)
#define RD3(x,y,z) scanf("%d %d %d",&x,&y,&z)
#define RDL1(x) scanf("%lld",&x)
#define RDL2(x,y) scanf("%lld %lld",&x,&y)
#define RDL3(x,y,z) scanf("%lld %lld %lld",&x,&y,&z)
#define CLR(x) memset(x,0,sizeof(x))
#define NEG(x) memset(x,0xff,sizeof(x))
#define maxn (200000+10)
#define maxm (1000000+10)
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mod (1000000007)
#define pi acos(-1)
#define eps 1e-14
#define acc ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define INF(x) memset(x,inf,sizeof(x))
#define CLRQ(Q) while(!(Q).empty())(Q).pop()
#define see(x) (cerr<<(#x)<<'='<<(x)<<' ')
#define NL printf("\n")
#define fi freopen("C:\\Users\\Administrator\\Desktop\\in","r",stdin)
#define fo freopen("C:\\Users\\Administrator\\Desktop\\out","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int head[maxn],to[maxn],pre[maxn],tot;
ll dis[maxn][11],l[maxn];
int n,m,k;
void adde(int u,int v,ll c)
{
	to[++tot]=v,pre[tot]=head[u],head[u]=tot,l[tot]=c;
}
struct node
{
	int to;
	ll len;
	int step;
};
struct cmp
{
	bool operator()(node a,node b)
	{
		if(a.len!=b.len)return a.len>b.len;
		else return a.step>b.step;
	}
};
priority_queue<node,vector<node>,cmp>Q;
bool exd[maxn][11];
void dij()
{
	CLR(exd);while(!Q.empty())Q.pop();
	INF(dis);for(int i=0;i<=k;i++)dis[1][i]=0;
	Q.push(node{1,0,0});
	while(!Q.empty())
	{
		node p=Q.top();Q.pop();
		int u=p.to;
		ll len=p.len;
		int st=p.step;
		if(exd[u][st])continue;
		exd[u][st]=1;
		for(int i=head[u];i;i=pre[i])
		{
			int v=to[i];
			if(st<k&&!exd[v][st+1]&&dis[v][st+1]>len)
			{
				dis[v][st+1]=len;
				Q.push(node{v,len,st+1});
			}
			if(!exd[v][st]&&dis[v][st]>len+l[i])
			{
				dis[v][st]=len+l[i];
				Q.push(node{v,len+l[i],st});
			}
		}
	}
}
int main()
{
	int ttt;RD1(ttt);while(ttt--)
	{
		CLR(head);tot=0;
		RD3(n,m,k);for(int i=1;i<=m;i++)
		{
			int u,v;ll c;RD2(u,v);RDL1(c);
			if(u==v)continue;
			adde(u,v,c);
		}
		dij();
		printf("%lld\n",dis[n][k]);
	}
	return 0;
}
/*
1
3 5 0
1 2 1
2 3 2
2 3 3
2 3 1
1 3 100
*/

The writing on the wall

巧妙计数问题,按子矩形的某个顶点(代码里是左下角)枚举
总体思路:
关键优化:随着矩形宽度增加,以某一点为左下角的矩形能达到的高度递减
同时用h[]缓存该列的最高高度
#include<bits/stdc++.h>
#define RD1(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d %d",&x,&y)
#define RD3(x,y,z) scanf("%d %d %d",&x,&y,&z)
#define RDL1(x) scanf("%lld",&x)
#define RDL2(x,y) scanf("%lld %lld",&x,&y)
#define RDL3(x,y,z) scanf("%lld %lld %lld",&x,&y,&z)
#define CLR(x) memset(x,0,sizeof(x))
#define NEG(x) memset(x,0xff,sizeof(x))
#define maxn (200000+10)
#define maxm (1000000+10)
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mod (1000000007)
#define pi acos(-1)
#define eps 1e-14
#define acc ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define INF(x) memset(x,inf,sizeof(x))
#define CLRQ(Q) while(!(Q).empty())(Q).pop()
#define see(x) (cerr<<(#x)<<'='<<(x)<<' ')
#define NL printf("\n")
#define fi freopen("C:\\Users\\Administrator\\Desktop\\in","r",stdin)
#define fo freopen("C:\\Users\\Administrator\\Desktop\\out","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
bool mp[100005][105];
int n,m,k;
int h[105];
int main()
{
	int ks=1;
	int ttt;RD1(ttt);while(ttt--)
	{
		CLR(mp);CLR(h);RD3(n,m,k);
		ll ans=0;
		while(k--){
			int x,y;RD2(x,y);mp[x][y]=1;
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)if(mp[i][j])h[j]=i;
			for(int j=1;j<=m;j++)
			{
				int Minh=inf;
				for(int c=j;c<=m;c++)
				{
					Minh=min(Minh,i-h[c]);
					ans+=Minh;
				//	cout<<ans<<endl;
				}
			}
		}
		printf("Case #%d: %lld\n",ks++,ans);
	}
	return 0;
}