CCPC Wannafly Winter Camp Div2 部分题解
Day 1, Div 2, Prob. B - 吃豆豆
题目大意
wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果,糖果只存在一秒,下一秒就会消失。
假如wls第\(k\)秒在第\(i\)行第\(j\)列的格子上,满足\(T[i][j]|k\),则wls会得到一个糖果。
wls每一秒只可以上下左右移动一格或停在原地。
请问wls从指定的\(S(xs,ys)\)出发到达指定的\(T(xt,yt)\),并且在路上得到至少\(C\)个糖果最少需要多少时间?
wls在\(S\)的初始时间是第0秒。
\]
解题思路
\(dp[i][j][k]\)表示吃到至少\(k\)颗豆豆,并且停在\((i,j)\)处的最少时间(“最少”其实有些不准确,这个后面再解释)。那么\(dp[i][j][1]\)就可以这样求出来了:
\]
\(\Delta t\)主要用于对\(T[i][j]\)取整,注意\(dp[xs][ys][1]\)就等于\(T[xs][ys]\)。接下来可以递推求\(dp[i][j][k]\)了:
\]
同样\((i',j')\)和\((i,j)\)相同时也要特殊考虑。
所以重新说明一下\(dp[i][j][k]\)的意义。它表示吃到至少\(k\)颗豆豆,并且停在\((i,j)\)的某个时间。这个时间满足:给定\(k\),由所有的\(dp[i'][j'][k]\)走到\((i,j)\),取最小值就是至少吃\(k\)颗豆豆,并且停在\((i,j)\)处的最少时间。因为由\(dp[i'][j'][k-1]\)转移到\(dp[i][j][k]\)时,路途上可能吃了豆豆,但这一定也会被某个\(dp[i''][j''][k]\)存储起来。
还是有点难理解,\(dp\)的题还是要多做一些才能有这样的思路。
#include <bits/stdc++.h>
typedef long long ll;
const int inf=0x3f3f3f3f;
const double eps=1e-5;
const int mod=1000000007;
const int maxn=10;
const int maxm=1018;
using namespace std;
int t[maxn+5][maxn+5];
int dp[maxn+5][maxn+5][maxm+10];
int dist(int x1,int y1,int x2,int y2)
{
return abs(x1-x2)+abs(y1-y2);
}
int main()
{
int n,m,c;
scanf("%d%d%d",&n,&m,&c);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",t[i]+j);
int xs,ys,xt,yt;
scanf("%d%d%d%d",&xs,&ys,&xt,&yt);
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(i!=xs||j!=ys)
dp[i][j][1]=(dist(xs,ys,i,j)+t[i][j]-1)/t[i][j]*t[i][j];
else
dp[i][j][1]=t[i][j];
}
for(int k=2;k<=c;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int ii=1;ii<=n;ii++)
for(int jj=1;jj<=m;jj++)
{
int temp;
if(ii==i&&jj==j)
temp=dp[ii][jj][k-1]+t[ii][jj];
else
temp=(dp[ii][jj][k-1]+dist(ii,jj,i,j)+t[i][j]-1)/t[i][j]*t[i][j];
dp[i][j][k]=min(dp[i][j][k],temp);
}
int ans=inf;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int temp=dp[i][j][c]+dist(i,j,xt,yt);
ans=min(ans,temp);
}
}
printf("%d\n",ans);
return 0;
}
Day 4, Div 2, Prob. G - 置置置换
题目大意
wls有一个整数\(n\),他想请你算一下有多少\(1...n\)的排列(permutation)满足:对于所有的\(i(2\leq i\leq n)\),若\(i\)为奇数,则\(a[i-1]<a[i]\),否则\(a[i-1]>a[i]\)。请输出答案mod 1e9+7。
\]
解题思路
\(dp[i][j]\)表示使用\(1...i\),开头为\(j\)的符合条件的排列数。
容易发现,将\(dp[i][j]\)排列对\(i+1\)取补,在开头加上一个比\(i+1-j\)大的数\(j'\),再把不比\(j'\)小的数都加一,就构造了一个新的\(1...i+1\)的排列。转移方程如下:
\]
容易发现,给定\(j\),这样构造是不重不漏的:每个\(dp[i][j]\),都可以有一个\(dp[i-1][j']\)与之对应;而每个\(dp[i-1][j']\),都可以对指定的\(j\),构造出一个\(dp[i][j]\)。
再利用一个前缀和,将复杂度降到\(O(n^2)\)。
#include <bits/stdc++.h>
typedef long long ll;
const int inf=0x3f3f3f3f;
const double eps=1e-5;
const int mod=1000000007;
const int maxn=1000;
const int maxm=300000;
using namespace std;
ll dp[maxn+10][maxn+10];
int main()
{
int n;
scanf("%d",&n);
memset(dp,0,sizeof(dp));
dp[1][1]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
dp[i][j]=(dp[i-1][i-1]-dp[i-1][i-j])%mod;
}
for(int j=1;j<=i;j++)
dp[i][j]=(dp[i][j]+dp[i][j-1])%mod;
}
printf("%lld\n",(dp[n][n]%mod+mod)%mod);
return 0;
}
Day 5, Div 2, Prob. F - Kropki
题目大意
你有一个\(1\)到\(n\)的排列 \(p_1\), \(p_2\), ... , \(p_n\),对于所有的\(i(1\leq i\leq n-1)\), 如果\(p_i\)和\(p_{i+1}\)中,有一个数是另一个数的两倍,那么这两个数之间标一个1,否则标0。
给定及长度为\(n-1(2\leq n\leq 15)\)的01串\(str[1:n-1]\),问有多少\(1\)到\(n\)的排列对应该01串。
解题思路
状压DP。\(dp[i][j][k]\)表示\(1...i\)位,使用过的数字状态是\(j\),末位是\(k\)的排列数。
当\(i\)与\(i+1\)之间标1时,若\(k\times 2\leq n\)且未被使用,则\(dp[i][j][k]\)可以向\(dp[i+1][j'][k\times 2]\)转移:
\]
同理可得:
\]
\]
#include<bits/stdc++.h>
typedef long long ll;
const int inf=0x3f3f3f3f;
const double eps=1e-5;
const double pi=3.141592653589793;
const int mod=1000000007;
const int maxn=1000;
const int maxm=1000;
using namespace std;
char str[maxn+10];
int dp[20][40000][20];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",str+1);
memset(dp,0,sizeof(dp));
for(int i=1; i<=15; i++)
dp[1][1<<(i-1)][i]=1;
for(int i=1; i<=n-1; i++)
for(int j=1;j<=(1<<n)-1;j++)
for(int k=1;k<=n;k++)
if(dp[i][j][k]>0)
{
if(str[i]=='1')
{
if(k%2==0&&(j&(1<<((k/2)-1)))==0)
dp[i+1][j|(1<<((k/2)-1))][k/2]=(dp[i+1][j|(1<<((k/2)-1))][k/2]+dp[i][j][k])%mod;
if(k*2<=n&&(j&(1<<((k*2)-1)))==0)
dp[i+1][j|(1<<((k*2)-1))][k*2]=(dp[i+1][j|(1<<((k*2)-1))][k*2]+dp[i][j][k])%mod;
}
else
{
for(int tmp=1;tmp<=n;tmp++)
if((k%2==1||tmp!=k/2)&&tmp!=k*2&&(j&(1<<((tmp)-1)))==0)
dp[i+1][j|(1<<((tmp)-1))][tmp]=(dp[i+1][j|(1<<((tmp)-1))][tmp]+dp[i][j][k])%mod;
}
}
ll ans=0;
for(int i=1;i<=n;i++)
ans=(ans+1LL*dp[n][(1<<n)-1][i])%mod;
printf("%lld\n",ans);
return 0;
}
CCPC Wannafly Winter Camp Div2 部分题解的更多相关文章
- 2020 CCPC Wannafly Winter Camp Day1 C. 染色图
2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...
- 2020 CCPC Wannafly Winter Camp Day1-F-乘法
题目传送门 sol:二分答案$K$,算大于$K$的乘积有多少个.关键在于怎么算这个个数,官方题解上给出的复杂度是$O(nlogn)$,那么计算个数的复杂度是$O(n)$的.感觉写着有点困难,自己写了一 ...
- 2020 CCPC Wannafly Winter Camp Day1 Div.1& F
#include<bits/stdc++.h> #define forn(i, n) for (int i = 0; i < int(n); i++) #define fore(i, ...
- 2020 CCPC Wannafly Winter Camp Day1 - I. K小数查询(分块)
题目链接:K小数查询 题意:给你一个长度为$n$序列$A$,有$m$个操作,操作分为两种: 输入$x,y,c$,表示对$i\in[x,y] $,令$A_{i}=min(A_{i},c)$ 输入$x,y ...
- 2020 CCPC Wannafly Winter Camp Day2-K-破忒头的匿名信
题目传送门 sol:先通过AC自动机构建字典,用$dp[i]$表示长串前$i$位的最小代价,若有一个单词$s$是长串的前$i$项的后缀,那么可以用$dp[i - len(s)] + val(s)$转移 ...
- 2019 wannafly winter camp day 3
2019 wannafly winter camp day 3 J 操作S等价于将S串取反,然后依次遍历取反后的串,每次加入新字符a,当前的串是T,那么这次操作之后的串就是TaT.这是第一次转化. 涉 ...
- 2019 wannafly winter camp
2019 wannafly winter camp Name Rank Solved A B C D E F G H I J K day1 9 5/11 O O O O O day2 5 3/11 O ...
- CCPC、Petrozavodsk Camp、OpenCup 题解汇总
省赛 \([\text{2021.11.30}]\) 2021 Jilin Collegiate Programming Contest 全部完成. \([\text{2021.12.25}]\) 2 ...
- 2019 wannafly winter camp day5-8代码库
目录 day5 5H div2 Nested Tree (树形dp) 5F div2 Kropki (状压dp) 5J div1 Special Judge (计算几何) 5I div1 Sortin ...
随机推荐
- Python算法——《算法图解》笔记
算法目录 二分查找 大O表示法 选择排序 递归 快速排序,分而治之(D&C) 散列表——字典 广度优先搜索——BFS Dijkstra算法 贪婪算法 二分查找 # 要求list是有序表,num ...
- HTML学习 day04
1.字体.文本声明 声明语句必须要包含在{}号之中: 属性和属性值之间用":"分隔: 当有多个属性时,用":"进行区分: 在书写属性时属性之间使用空格.换行等, ...
- 推荐几个不错的console调试技巧
在我们的日常前端开发中,使用最频繁的莫过于使用console.log在浏览器的控制台中打印出我们需要调试的信息,但是大部分人可能跟之前的我一样,没有意识到其实console除了log方法以外,还有很多 ...
- 学会使用这些,你的Windows可能会焕然一新
星选哥用Windows也已经好多年了,今天用室友的电脑才发现,桌面真可以影响一个人的心情,从而影响工作,学习,生活. 所以准备推荐一些好用且轻量的小工具,让你时时刻刻有个好心情. 室友的桌面(还有很多 ...
- scala学习系列二
一 scala语言开发注意事项: 1 Scala程序的执行入口是main()函数 2 Scala语言严格区分大小写. 3 Scala方法由一条条语句构成,每个语句后不需要分号(Scala语言会在每行后 ...
- 分布式远程调用SpringCloud-Feign的两种具体操作方式(精华)
一 前言 几大RPC框架介绍 1.支持多语言的RPC框架,google的gRPC,Apache(facebook)的Thrift 2.只支持特定语言的RPC框架,例如新浪的Motan 3.支持服务治理 ...
- length of the longest substring without repeating character
Given a string, find the length of the longest substring without repeating characters. 来源:力扣(LeetCod ...
- 【JavaEE】之SSM-Maven依赖积累
本帖中收集JavaEE SSM框架使用的Maven版本库中的依赖.本帖持续更新...... 日志输出: <dependency> <groupId>commons-loggin ...
- KFC-位置分页爬虫
import requests import json if name == 'main': #记录总数 raw_count=0 #查询页数 page=1 #存储数据 data=[] #判断有无数据条 ...
- NSAttributedString可以强制转换为NSMutableAttributedString类型吗?下面这代码有什么问题 为什么报错
-(void)insetEmotion:(EmotionModel*)emotionModel{ if(emotionModel.code){ /** 在TextView中插入图片首选要知道光标的位置 ...