20160609常规赛总结

来源:互联网 发布:java二次开发平台 编辑:程序博客网 时间:2024/05/21 11:08

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=1dp[i]
为了让ans最大我们最好最大化dp[i]
然后转移的时候dp[i]=i1i=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;}
0 0
原创粉丝点击