kao这场比赛也是醉了。
下午刚骑完环城晚上醉醺醺的。
敲完以后觉得感觉很好,就估分估了240
被小C严重鄙视说不可能
然后第一题爆0了==
现在说一下题目。
T1
模拟题,因为两句话写反了导致全部都T了。
T2
一道裸的前缀和优化dp
算了还是写的详细点吧==
Sources Codeforces 645 E
Description
给出长度为m的字符串以及k个小写字母,求再任意加上n个字符(在k的范围内)总串不同子序列的个数的最大值。
注意:空串也计 入统计。
Solution
定义dp[i]表示以str[i]为结尾的与之前的不同子序列的个数
那么转移的时候只要转移到之前相同处即可。
然后ans=
∑n+mi=1
dp[i]
为了让ans最大我们最好最大化dp[i]
然后转移的时候dp[i]=
∑i−1i=last[str[i]]
dp[i]
最大化的dp[i]也可以同时最大化后面的dp值。
关于后面的n个字母,由于转移方程一定,我们希望让last[str[i]]尽量小就好了。
作为全场唯一个A掉的现在想来还有点小激动。。
虽然它是前缀和优化dp的裸体。
T3
Sources Codeforces 152E(有改编)
Description
给定一个n*m的矩阵,以及k个坐标,求包含k个坐标的的四联通块的点的权值的最小值。
Solution
这题给了很多的水分点。最小最简单的那个挂了==
现在一万个不爽。。整整少了10分==
表程是所谓状压dp
这个dp是用填表(坑)法来实现的。
首先我们令dp[i][j][S]表示点(i,j)覆盖状态为S的最小点权和。
它可以向四周填坑。
可以自己填自己,当然这要有个前提就是刚好自己里有一个状态覆盖和当前没有交集。
这样的状态好像很乱。
瞎逼跑个最短路就好了。。
放个源代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int M=105;
const int Ss=1<<8;
const int INF=1<<30;
int dp[M][M][Ss],A[M][M],n,m,k,mx,my,ans;
bool mark[M][M][Ss];
struct node{int x,y;}c[M];
struct status{
int x,y,S,dis;
inline bool operator < (const status &tmp)const{
return dis>tmp.dis;
}
};
int rx[]={0,1,0,-1};
int ry[]={1,0,-1,0};
priority_queue<status>que;
inline void Min(int &a,int b){if(a>b)a=b;}
inline bool check(const int &x,const int &y){return x>0&&x<=n&&y>0&&y<=m;}
inline void bfs(){
ans=INF;
memset(dp,127,sizeof(dp));
for(int i=0;i<=k;++i)
que.push((status){c[i].x,c[i].y,1<<i,dp[c[i].x][c[i].y][1<<i]=0});
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
que.push((status){i,j,0,dp[i][j][0]=0});
for(;!que.empty();){
status v=que.top();que.pop();
int x=v.x,y=v.y,S=v.S,dis=v.dis,dist=dis+A[x][y];
if(mark[x][y][S])continue;
mark[x][y][S]=1;
for(int i=0;i<4;++i){
int nx=x+rx[i],ny=y+ry[i];
if(!check(nx,ny))continue;
if(dist<dp[nx][ny][S])que.push((status){nx,ny,S,dp[nx][ny][S]=dist});
}
for(int St=0;St<1<<k+1;++St){
if(St&S||!mark[x][y][St])continue;
int tS=St|S,val=dis+dp[x][y][St];
if(val<dp[x][y][tS]){
que.push((status){x,y,tS,dp[x][y][tS]=val});
}
}
}
int S=0;
for(int i=0;i<=k;++i)S|=1<<i;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
Min(ans,dp[i][j][S]+A[i][j]);
ans-=A[c[0].x][c[0].y];
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
scanf("%d",A[i]+j);
for(int i=0;i<=k;++i)
scanf("%d %d",&c[i].x,&c[i].y);
bfs();
cout<<ans<<endl;
return 0;
}