【Kickstart】2018 Round D - Funniest Word Search

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lemonmillie/article/details/94497249

解法

第一步,分别统计以(i,j)结尾的,长度不超过k的单词总长度,横着和竖着分别记作h[i,j,k]v[i,j,k]

然后我们考虑DP,状态为f[i1,j1,i2,j2]
四重循环遍历的时候:

  1. i2每增加1的时候,总是从f[i1,j1,i2,j1]开始的,这是竖着的一列,所以我们需要知道这一列里:

    1. 横着,以区间(i1,j1)(i2,j1)之间的字符结尾,长度不超过1的单词总长度,假设这部分为A
    2. 竖着,在区间(i1,j1)(i2,j1)之间的单词总长度,假设这部分为B

    那么有初始条件:f[i1,j1,i2,j1]=A+B

  2. i2固定,j2每增加1的时候,相当于与f[i1,j1,i2,j1-1]相比增加了竖着的一列,与上一条相似地,我们需要增加:

    1. 横着,以区间(i1,j2)(i2,j2)之间的字符结尾,长度不超过j2-j1+1的单词总长度,假设这部分为C
    2. 竖着,在区间(i1,j2)(i2,j2)之间的单词总长度,假设这部分为D

    那么递推方程为:f[i1,j1,i2,j2]=f[i1,j1,i2,j2-1]+C+D

如何求第一部分呢?我们可以对h数组,在固定j,k的情况下,对i轴求前缀和,记作cumv[i,j,k]=cumv[i-1,j,k]+h[i,j,k],这样就有:
A = cumv[i2,j1,1]-cumv[i1-1,j1,1]
C = cumv[i2,j2,j2-j1+1]-cumv[i1-1,j2,j2-j1+1]

对于第二部分,我们可以用cumh[i,j,k]记录区间(i-k+1,j)(i,j)之间的单词总长度,它可以这么求:
cumh[i,j,k] = cumh[i-1,j,k-1]+v[i,j,k]
这样就有:
B = cumh[i2,j1,i2-i1+1]
D = cumh[i2,j2,i2-i1+1]

注意所有的数组都用int会超内存限制,我们可以分析一下:

  1. 数组vh最多是1000个单词长度为100,甚至题目还有条件限制所有单词长度加起来不超过5000,所以它们的值最大也不会超过10**4(假如正逆要算两遍的话)
  2. 然后cumvcumh相当于是对某一维进行累加,所以多100倍,即10**6
  3. 然后是f,又进行了累加,所以大约再涨100倍,即10**8

可见3个都不会超过int,但是,在比较分数大小的时候,如果像我一样用的是乘法而不是除法,那么中间结果有可能超过int,需要转换成long long

#include <stdio.h>
#include <string>
#include <iostream>
#include <memory.h>
#include <stdlib.h>
#include <unordered_set>
#include <unordered_map>
#include <cmath>
#include <vector>
#include <algorithm>

#define MAXN 110
#define NINF 0x80000000


using namespace std;

typedef long long lld;
typedef unordered_multiset<string> DICT;

string matrix[MAXN];
unordered_map<int,DICT> words;
int v[MAXN][MAXN][MAXN],h[MAXN][MAXN][MAXN];
int cumv[MAXN][MAXN][MAXN],cumh[MAXN][MAXN][MAXN];
int f[MAXN][MAXN][MAXN][MAXN];
int r,c,w;
lld score,size,cnt;

void insert(string &word) {
    int l = word.size();
    if(words.find(l)==words.end())
        words[l] = DICT();
    words[l].insert(word);
}

void reduce(lld &a,lld &b) {
    lld x=a,y=b;
    if(x<y) {
        x^=y;y^=x;y^=x;
    }
    while(x%y!=0) {
        int tmp = y;
        y = x%y;
        x = tmp;
    }
    a /= y,b/=y;
}

void newVal(int i1,int j1,int i2,int j2) {
    lld s = i2-i1+j2-j1+2;
    lld sc = f[i1][j1][i2][j2];
    if(sc*size>=score*s) {
        if(sc*size==score*s) cnt++;
        else {
            cnt = 1;
            score = f[i1][j1][i2][j2];
            size = s;
            reduce(score,size);
        }
    }
}

void solve() {
    score = 0, size = 1, cnt = 0;
    memset(v,0,sizeof(int)*MAXN*MAXN*MAXN);
    memset(h,0,sizeof(int)*MAXN*MAXN*MAXN);
    memset(cumv,0,sizeof(int)*MAXN*MAXN*MAXN);
    memset(cumh,0,sizeof(int)*MAXN*MAXN*MAXN);
    for(int i=1;i<=r;++i)
        for(int j=0;j<c;++j) {
            string ver="";
            for(int k=1;k<=i;++k) {
                v[i][j][k] = v[i][j][k-1];
                ver += matrix[i-k+1][j];
                if(words.find(k)!=words.end()) {
                    DICT &dict = words[k];
                    v[i][j][k]+=dict.count(ver)*k;
                }
            }
            string hor="";
            for(int k=1;k<=1+j;++k) {
                h[i][j][k] = h[i][j][k-1];
                hor += matrix[i][j-k+1];
                if(words.find(k)!=words.end()) {
                    DICT &dict = words[k];
                    h[i][j][k]+=dict.count(hor)*k;
                }
            }
        }

    for(int i=1;i<=r;++i)
        for(int j=0;j<c;++j) {
            for(int k=1;k<=1+j;++k) {
                cumv[i][j][k] = cumv[i-1][j][k]+h[i][j][k];
            }
            for(int k=1;k<=i;++k) {
                cumh[i][j][k] = cumh[i-1][j][k-1]+v[i][j][k];
            }
        }

    memset(f,0,sizeof(int)*MAXN*MAXN*MAXN*MAXN);
    for(int i1=1;i1<=r;++i1)
        for(int j1=0;j1<c;++j1) {
            for(int i2=i1;i2<=r;++i2) {
                f[i1][j1][i2][j1] = cumh[i2][j1][i2-i1+1]+cumv[i2][j1][1]-cumv[i1-1][j1][1];
                newVal(i1,j1,i2,j1);
                for(int j2=j1+1;j2<c;++j2) {
                    f[i1][j1][i2][j2] = f[i1][j1][i2][j2-1]+cumh[i2][j2][i2-i1+1]+cumv[i2][j2][j2-j1+1]-cumv[i1-1][j2][j2-j1+1];
                    newVal(i1,j1,i2,j2);
                }
            }
        }
}

int main() {
//    freopen("obj.txt","r",stdin);
//    freopen("my.out","w",stdout);
    int t;
    scanf("%d",&t);
    for(auto round=1;round<=t;++round) {
        words.clear();
        scanf("%d%d%d\n",&r,&c,&w);
        for(int i=1;i<=r;++i)
            getline(cin,matrix[i]);
        string str;
        for(int i=0;i<w;++i) {
            getline(cin,str);
            insert(str);
            reverse(str.begin(),str.end());
            insert(str);
        }
        solve();
        reduce(score,size);
        printf("Case #%d: %lld/%lld %lld\n",round,score,size,cnt);
    }
}
展开阅读全文

c word search segmentation fault

02-28

[code=C/C++][/code]rnrn 在putty 下用 ./square < data1 运行 从data1中的字母矩阵和单词从找出所给单词,横向纵向斜向正反都行。rnrnrn输入文件如下rnrnS T E L B M T F E Y D E E P S R T C I A E E (后一个空格加转行符)rnN N E L I T R L B D E T A R E M U N E T Y LrnN O I T A N I M I R C N I F L E S S E N T ArnA U I D E W A R R A N T N U P R U S S E R PrnP G S G E A L P A P B A N P S A S S N M E ArnC O N S I T U T I O N D E E C W S O O H P DrnS V W D E L A N E E J A M E S M A D I S O NrnA E D E S N E G R J C U L T N O H L T I R ArnA R C E R R T R E E S B O N E E I D N N P RrnS N J U D I C I A L A S S E C O R P E U D IrnS M R A R A E B W B E S S M E O A U V P E MrnO E O I A I L N O U C D O D S S E N N I G RrnL N I D G Y T R C O M P E N S A T I O N N DrnD T O Z E H P Y N D R L E E A O H S C O I BrnI T P S U E T G O L U Z M M R B E H P I R TrnE O I E A R R S U U I B H A Y L L M S T F ArnR I N R E E E F U T L V Q U A R T E R I N GrnS I D B S R R D I Y E N I G M I A N A T I RrnS Q I S E B S C N S P E E C H R O T A E Y NrnD L C M I L I T I A F L R N C A T S S P S ErnR U T E D Y L E B I L C O H M L E T E S Y YrnL S T R T E W Z L I O S A E N S A E I Y A LrnAMENDMENTrnASSEMBLYrnBAILrnBEARARMSrnCITIZENrnCIVILrnCOMPENSATIONrnCONGRESSrnCONSITUTIONrnCONVENTIONSrnDELEGATEDrnDOUBLEJEOPARDYrnDUEPROCESSrnENUMERATEDrnFREEDOMrnGOVERNMENTrnILLEGALrnINDICTrnINFRINGEDrnJAMESMADISONrnJUDICIALrnLAWSUITrnLIBELrnLIBERTYrnLIFErnMILITIArnMIRANDArnNECESSARYrnPEACEABLYrnPEERSrnPETITIONrnPOWERrnPRESSrnPROBABLECAUSErnPROPERTYrnPUNISHMENTSrnQUARTERINGrnRELIGIONrnRIGHTSrnSEARCHrnSECURITYrnSEIZURErnSELFINCRIMINATIONrnSLANDERrnSOLDIERSrnSPEECHrnSPEEDYrnTRIALrnUNREASONABLErnWARRANTrnWITNESSrnrn代码如下:rn#includern#includern#includern#define M 50rn#define S 20rnrnint mark[M][M]=0;rnrnint getData(char matr[][M],int *size);rnint isit(char matr[][M],int r,int c, int rd, int cd,char buf[S]);rnvoid printWord(char matr[][M],int *size);rnrnvoid printWord(char matr[][M], int *size)rn int i,j;rn for(i=0;i<*size;i++)rn for(j=0;j<*size;j++)rn if (mark[i][j]==1)rn printf("%c",matr[i][j]);rn elsern printf("%c",'0');rn rn printf("%c",'\n');rn rnrnrnrnint isit(char matr[][M],int r,int c, int rd, int cd,char buf[S])rnrn int i,j;rn int length=strlen(buf);rn int step=0;rn while(steplength || r>length )rn return 0;rn else if (matr[r][c]!=buf[step])rn return 0;rn elsern r+=rd;rn c+=cd;rn step++;rn printf("%d",step);rn rn rn if (step==length)rn mark[r][c]=1;rn for(i=0;i 论坛

没有更多推荐了,返回首页